#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "../benchmarks/test_data.hpp"
#include "parser_comparison.hpp"
#include <doctest/doctest.h>

/**
 * @brief Test helper that uses parser comparison to validate both parsers.
 *
 * This function tests that either both parsers reject the input, or both
 * accept it and produce equivalent CommitRequest objects.
 */
void test_parser_comparison(const std::string &json_str,
                            const std::string &test_name) {
  INFO("Testing: " << test_name);
  INFO("JSON: " << json_str);

  auto result = ParserComparison::compare_parsers(json_str);

  INFO("Comparison result: " << ParserComparison::result_to_string(result));
  if (!ParserComparison::get_last_error().empty()) {
    INFO("Error details: " << ParserComparison::get_last_error());
  }

  // Accept either both success or both failure - reject inconsistencies
  REQUIRE((result == ParserComparison::ComparisonResult::BothSuccess ||
           result == ParserComparison::ComparisonResult::BothFailure));
}

TEST_CASE("Parser Comparison - Basic Cases") {
  SUBCASE("Simple valid request") {
    test_parser_comparison(R"({
            "request_id": "test123",
            "leader_id": "leader456",
            "read_version": 12345
        })",
                           "Simple valid request");
  }

  SUBCASE("Minimal valid request (no request_id)") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345
        })",
                           "Minimal valid request");
  }

  SUBCASE("Request with preconditions") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "preconditions": [
                {
                    "type": "point_read",
                    "version": 12340,
                    "key": "dGVzdA=="
                }
            ]
        })",
                           "Request with preconditions");
  }

  SUBCASE("Request with operations") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "operations": [
                {
                    "type": "write",
                    "key": "dGVzdA==",
                    "value": "dmFsdWU="
                },
                {
                    "type": "delete",
                    "key": "dGVzdDI="
                }
            ]
        })",
                           "Request with operations");
  }

  SUBCASE("Complex request with both preconditions and operations") {
    test_parser_comparison(R"({
            "request_id": "complex-test",
            "leader_id": "leader789",
            "read_version": 98765,
            "preconditions": [
                {
                    "type": "point_read",
                    "version": 98764,
                    "key": "dGVzdEtleQ=="
                },
                {
                    "type": "range_read",
                    "begin": "c3RhcnQ=",
                    "end": "ZW5k"
                }
            ],
            "operations": [
                {
                    "type": "write",
                    "key": "dGVzdEtleQ==",
                    "value": "dGVzdFZhbHVl"
                },
                {
                    "type": "delete",
                    "key": "ZGVsZXRlS2V5"
                },
                {
                    "type": "range_delete",
                    "begin": "cmFuZ2VTdGFydA==",
                    "end": "cmFuZ2VFbmQ="
                }
            ]
        })",
                           "Complex request");
  }
}

TEST_CASE("Parser Comparison - Invalid Cases") {
  SUBCASE("Invalid JSON syntax") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": "not_a_number"
        })",
                           "Invalid JSON - string for number");
  }

  SUBCASE("Missing required leader_id") {
    test_parser_comparison(R"({
            "request_id": "test123",
            "read_version": 12345
        })",
                           "Missing leader_id");
  }

  SUBCASE("Missing required read_version") {
    test_parser_comparison(R"({
            "request_id": "test123",
            "leader_id": "leader456"
        })",
                           "Missing read_version");
  }

  SUBCASE("Empty leader_id") {
    test_parser_comparison(R"({
            "request_id": "test123",
            "leader_id": "",
            "read_version": 12345
        })",
                           "Empty leader_id");
  }

  SUBCASE("Invalid precondition - missing key") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "preconditions": [
                {
                    "type": "point_read"
                }
            ]
        })",
                           "Invalid precondition - missing key");
  }

  SUBCASE("Invalid precondition - missing begin for range_read") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "preconditions": [
                {
                    "type": "range_read",
                    "end": "dGVzdFo="
                }
            ]
        })",
                           "Invalid precondition - missing begin");
  }

  SUBCASE("Invalid precondition - missing end for range_read") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "preconditions": [
                {
                    "type": "range_read",
                    "begin": "dGVzdA=="
                }
            ]
        })",
                           "Invalid precondition - missing end");
  }

  SUBCASE("Invalid operation - missing key for write") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "operations": [
                {
                    "type": "write",
                    "value": "dmFsdWU="
                }
            ]
        })",
                           "Invalid operation - missing key");
  }

  SUBCASE("Invalid operation - missing value for write") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "operations": [
                {
                    "type": "write",
                    "key": "dGVzdA=="
                }
            ]
        })",
                           "Invalid operation - missing value");
  }

  SUBCASE("Invalid operation - missing key for delete") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "operations": [
                {
                    "type": "delete"
                }
            ]
        })",
                           "Invalid operation - missing key for delete");
  }

  SUBCASE("Invalid operation - missing begin for range_delete") {
    test_parser_comparison(
        R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "operations": [
                {
                    "type": "range_delete",
                    "end": "dGVzdFo="
                }
            ]
        })",
        "Invalid operation - missing begin for range_delete");
  }

  SUBCASE("Invalid operation - missing end for range_delete") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "operations": [
                {
                    "type": "range_delete",
                    "begin": "dGVzdA=="
                }
            ]
        })",
                           "Invalid operation - missing end for range_delete");
  }

  SUBCASE("Malformed JSON") {
    test_parser_comparison(R"({
            "leader_id": "leader456"
            "read_version": 12345
        })",
                           "Malformed JSON - missing comma");
  }

  SUBCASE("Invalid precondition type") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "preconditions": [
                {
                    "type": "invalid_type",
                    "key": "dGVzdA=="
                }
            ]
        })",
                           "Invalid precondition type");
  }

  SUBCASE("Invalid operation type") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "operations": [
                {
                    "type": "invalid_operation",
                    "key": "dGVzdA=="
                }
            ]
        })",
                           "Invalid operation type");
  }
}

TEST_CASE("Parser Comparison - Edge Cases") {
  SUBCASE("Empty arrays") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "preconditions": [],
            "operations": []
        })",
                           "Empty arrays");
  }

  SUBCASE("Empty base64 strings") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "operations": [
                {
                    "type": "write",
                    "key": "",
                    "value": ""
                }
            ]
        })",
                           "Empty base64 strings");
  }

  SUBCASE("Zero read_version") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 0
        })",
                           "Zero read_version");
  }

  SUBCASE("Large read_version") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 9223372036854775807
        })",
                           "Large read_version");
  }

  SUBCASE("Precondition with zero version") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "preconditions": [
                {
                    "type": "point_read",
                    "version": 0,
                    "key": "dGVzdA=="
                }
            ]
        })",
                           "Precondition with zero version");
  }

  SUBCASE("Range operations with empty keys") {
    test_parser_comparison(R"({
            "leader_id": "leader456",
            "read_version": 12345,
            "preconditions": [
                {
                    "type": "range_read",
                    "begin": "",
                    "end": ""
                }
            ],
            "operations": [
                {
                    "type": "range_delete",
                    "begin": "",
                    "end": ""
                }
            ]
        })",
                           "Range operations with empty keys");
  }
}

TEST_CASE("Parser Comparison - Test Data") {
  SUBCASE("SIMPLE_JSON") {
    test_parser_comparison(weaseldb::test_data::SIMPLE_JSON,
                           "SIMPLE_JSON test data");
  }

  SUBCASE("MEDIUM_JSON") {
    test_parser_comparison(weaseldb::test_data::MEDIUM_JSON,
                           "MEDIUM_JSON test data");
  }

  SUBCASE("COMPLEX_JSON") {
    test_parser_comparison(weaseldb::test_data::COMPLEX_JSON,
                           "COMPLEX_JSON test data");
  }

  SUBCASE("Generated large JSON") {
    // Test with a reasonably sized generated JSON to avoid extremely long test
    // times
    std::string large_json = weaseldb::test_data::generate_large_json(100);
    test_parser_comparison(large_json, "Generated large JSON (100 operations)");
  }
}

TEST_CASE("Parser Comparison - Stress Tests") {
  SUBCASE("Multiple operations of each type") {
    test_parser_comparison(R"({
            "request_id": "stress-test-operations",
            "leader_id": "stress-leader",
            "read_version": 1000000,
            "operations": [
                {
                    "type": "write",
                    "key": "a2V5MQ==",
                    "value": "dmFsdWUx"
                },
                {
                    "type": "write",
                    "key": "a2V5Mg==",
                    "value": "dmFsdWUy"
                },
                {
                    "type": "delete",
                    "key": "a2V5Mw=="
                },
                {
                    "type": "delete",
                    "key": "a2V5NA=="
                },
                {
                    "type": "range_delete",
                    "begin": "cmFuZ2UxX3N0YXJ0",
                    "end": "cmFuZ2UxX2VuZA=="
                },
                {
                    "type": "range_delete",
                    "begin": "cmFuZ2UyX3N0YXJ0",
                    "end": "cmFuZ2UyX2VuZA=="
                }
            ]
        })",
                           "Multiple operations of each type");
  }

  SUBCASE("Multiple preconditions of each type") {
    test_parser_comparison(R"({
            "leader_id": "stress-leader",
            "read_version": 2000000,
            "preconditions": [
                {
                    "type": "point_read",
                    "version": 1999999,
                    "key": "cG9pbnQx"
                },
                {
                    "type": "point_read",
                    "version": 1999998,
                    "key": "cG9pbnQy"
                },
                {
                    "type": "range_read",
                    "version": 1999997,
                    "begin": "cmFuZ2UxX3N0YXJ0",
                    "end": "cmFuZ2UxX2VuZA=="
                },
                {
                    "type": "range_read",
                    "begin": "cmFuZ2UyX3N0YXJ0",
                    "end": "cmFuZ2UyX2VuZA=="
                }
            ]
        })",
                           "Multiple preconditions of each type");
  }

  SUBCASE("Deep nesting with many operations") {
    // Use the generate_large_json function which now properly encodes base64
    std::string stress_json = weaseldb::test_data::generate_large_json(50);
    test_parser_comparison(stress_json, "Deep nesting with many operations");
  }
}
