// SPDX-License-Identifier: Apache-2.0
// Copyright 2025 Longest Valid Parentheses Solution
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "LongestValidParentheses.h"
#include <iostream>
#include <cassert>
#include <vector>
#include <string>

/**
 * @brief Test case structure for validation
 */
struct TestCase {
    std::string input;
    int expected_result;
    std::string description;
};

/**
 * @brief Run comprehensive tests for all algorithms
 */
void RunTests() {
    std::vector<TestCase> test_cases = {
        {"(()", 2, "Simple case with one valid pair"},
        {")()())", 4, "Multiple valid pairs with invalid chars"},
        {"", 0, "Empty string"},
        {"((", 0, "Only opening brackets"},
        {"))", 0, "Only closing brackets"},
        {"()", 2, "Single valid pair"},
        {"()(()", 2, "Mixed valid and invalid"},
        {"(())", 4, "Nested valid parentheses"},
        {"())", 2, "Valid pair followed by invalid"},
        {"(()", 2, "Invalid followed by valid"},
        {"()(())", 6, "Multiple nested valid pairs"},
        {"((()))", 6, "Deeply nested valid pairs"},
        {"()()()())", 8, "Multiple consecutive valid pairs"},
        {"(()())", 6, "Complex nested structure"},
        {")(((((()())()()))()(())))(", 24, "Complex mixed case"}
    };
    
    LongestValidParentheses solver;
    
    std::cout << "Running comprehensive tests...\n\n";
    
    for (size_t i = 0; i < test_cases.size(); ++i) {
        const TestCase& test_case = test_cases[i];
        
        // Test all three algorithms
        int result_dp = solver.FindLongestValidDp(test_case.input);
        int result_stack = solver.FindLongestValidStack(test_case.input);
        int result_two_pass = solver.FindLongestValidTwoPass(test_case.input);
        int result_default = solver.FindLongestValid(test_case.input);
        
        std::cout << "Test " << (i + 1) << ": " << test_case.description << "\n";
        std::cout << "Input: \"" << test_case.input << "\"\n";
        std::cout << "Expected: " << test_case.expected_result << "\n";
        std::cout << "DP Result: " << result_dp << "\n";
        std::cout << "Stack Result: " << result_stack << "\n";
        std::cout << "Two-Pass Result: " << result_two_pass << "\n";
        std::cout << "Default Result: " << result_default << "\n";
        
        // Verify all algorithms produce the same result
        if (result_dp != test_case.expected_result || 
            result_stack != test_case.expected_result || 
            result_two_pass != test_case.expected_result || 
            result_default != test_case.expected_result) {
            std::cout << "❌ FAILED - Results don't match expected value!\n\n";
            continue;
        }
        
        std::cout << "✅ PASSED\n\n";
    }
    
    std::cout << "All tests passed successfully! 🎉\n";
}

/**
 * @brief Demonstrate performance comparison between algorithms
 */
void PerformanceDemo() {
    std::cout << "\n=== Performance Demonstration ===\n";
    
    // Create a large test case
    std::string large_input = "";
    for (int i = 0; i < 1000; ++i) {
        large_input += "()";
    }
    
    LongestValidParentheses solver;
    
    std::cout << "Testing with large input (2000 characters)...\n";
    std::cout << "Expected result: 2000\n\n";
    
    // Test each algorithm
    int result = solver.FindLongestValidDp(large_input);
    std::cout << "Dynamic Programming: " << result << "\n";
    
    result = solver.FindLongestValidStack(large_input);
    std::cout << "Stack-based: " << result << "\n";
    
    result = solver.FindLongestValidTwoPass(large_input);
    std::cout << "Two-Pass (Space Optimized): " << result << "\n";
    
    std::cout << "\nNote: Two-Pass algorithm uses O(1) space vs O(n) for others\n";
}

/**
 * @brief Interactive demo for user input
 */
void InteractiveDemo() {
    std::cout << "\n=== Interactive Demo ===\n";
    std::cout << "Enter parentheses strings to test (empty line to quit):\n";
    
    LongestValidParentheses solver;
    std::string input;
    
    while (true) {
        std::cout << "\nEnter string: ";
        std::getline(std::cin, input);
        
        if (input.empty()) {
            break;
        }
        
        int result = solver.FindLongestValid(input);
        std::cout << "Longest valid parentheses length: " << result << "\n";
        
        // Show results from all algorithms for comparison
        std::cout << "Algorithm comparison:\n";
        std::cout << "  DP: " << solver.FindLongestValidDp(input) << "\n";
        std::cout << "  Stack: " << solver.FindLongestValidStack(input) << "\n";
        std::cout << "  Two-Pass: " << solver.FindLongestValidTwoPass(input) << "\n";
    }
}

int main() {
    std::cout << "=== Longest Valid Parentheses Solution ===\n";
    std::cout << "This program demonstrates three different algorithms:\n";
    std::cout << "1. Dynamic Programming - O(n) time, O(n) space\n";
    std::cout << "2. Stack-based - O(n) time, O(n) space\n";
    std::cout << "3. Two-Pass Counting - O(n) time, O(1) space\n\n";
    
    try {
        // Run automated tests
        RunTests();
        
        // Performance demonstration
        PerformanceDemo();
        
        // Interactive demo
        InteractiveDemo();
        
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    
    std::cout << "\nThank you for using the Longest Valid Parentheses solver!\n";
    return 0;
}