// This file is generated by mkfile.py
// Date: 2026-06-25

#include <gtest/gtest.h>
#include <solution/22.h>

#include <algorithm>
#include <cstdlib>
#include <set>
#include <string>
#include <vector>

namespace
{
struct GeneratedParentheses
{
    char **data = nullptr;
    int size = 0;

    explicit GeneratedParentheses(int n)
    {
        data = generateParenthesis(n, &size);
    }

    ~GeneratedParentheses()
    {
        if (data == nullptr)
        {
            return;
        }

        for (int i = 0; i < size; ++i)
        {
            free(data[i]);
        }
        free(data);
    }
};

bool IsValidParentheses(const std::string &s, int pairCount)
{
    if ((int)s.size() != pairCount * 2)
    {
        return false;
    }

    int balance = 0;
    for (char c : s)
    {
        if (c == '(')
        {
            ++balance;
        }
        else if (c == ')')
        {
            --balance;
        }
        else
        {
            return false;
        }

        if (balance < 0)
        {
            return false;
        }
    }

    return balance == 0;
}
} // namespace

class GenerateParenthesisTest : public ::testing::Test
{
  protected:
    void AssertGeneratedEquals(int n, std::vector<std::string> expected)
    {
        GeneratedParentheses result(n);

        ASSERT_EQ(result.size, (int)expected.size());
        ASSERT_NE(result.data, nullptr);

        std::vector<std::string> actual;
        actual.reserve(result.size);
        for (int i = 0; i < result.size; ++i)
        {
            ASSERT_NE(result.data[i], nullptr);
            actual.emplace_back(result.data[i]);
        }

        std::sort(actual.begin(), actual.end());
        std::sort(expected.begin(), expected.end());
        EXPECT_EQ(actual, expected);
    }
};

TEST_F(GenerateParenthesisTest, Example1)
{
    AssertGeneratedEquals(3, {"((()))", "(()())", "(())()", "()(())", "()()()"});
}

TEST_F(GenerateParenthesisTest, Example2)
{
    AssertGeneratedEquals(1, {"()"});
}

TEST_F(GenerateParenthesisTest, TwoPairs)
{
    AssertGeneratedEquals(2, {"(())", "()()"});
}

TEST_F(GenerateParenthesisTest, FourPairsAreUniqueAndValid)
{
    GeneratedParentheses result(4);

    ASSERT_EQ(result.size, 14);
    ASSERT_NE(result.data, nullptr);

    std::set<std::string> unique;
    for (int i = 0; i < result.size; ++i)
    {
        ASSERT_NE(result.data[i], nullptr);
        std::string current(result.data[i]);

        EXPECT_TRUE(IsValidParentheses(current, 4)) << current;
        unique.insert(current);
    }

    EXPECT_EQ(unique.size(), 14u);
}
