#pragma once

#include "commit_request.hpp"
#include "json_commit_request_parser.hpp"
#include "nlohmann_reference_parser.hpp"
#include <string>

/**
 * @brief Test utility for comparing parser implementations.
 *
 * This class provides functionality to test that the weaseljson-based parser
 * and the nlohmann/json reference parser produce equivalent results.
 */
class ParserComparison {
public:
  enum class ComparisonResult {
    BothSuccess, // Both parsers succeeded and produced equivalent results
    BothFailure, // Both parsers failed (as expected)
    WeaselSuccessNlohmannFail, // Weasel succeeded but nlohmann failed
                               // (potential bug)
    NlohmannSuccessWeaselFail, // Nlohmann succeeded but weasel failed
                               // (potential bug)
    DifferentResults // Both succeeded but produced different CommitRequests
  };

  /**
   * @brief Compare two parser implementations on the same JSON input.
   * @param json_str The JSON string to parse with both parsers
   * @return ComparisonResult indicating the outcome of the comparison
   */
  static ComparisonResult compare_parsers(const std::string &json_str);

  /**
   * @brief Get a human-readable description of the comparison result.
   * @param result The comparison result
   * @return String description
   */
  static std::string result_to_string(ComparisonResult result);

  /**
   * @brief Get the last error message from comparison.
   * @return Error message or empty string
   */
  static const std::string &get_last_error() { return last_error_; }

private:
  static std::string last_error_;

  /**
   * @brief Compare two CommitRequest objects for equality.
   * @param req1 First request
   * @param req2 Second request
   * @return true if equivalent, false otherwise
   */
  static bool requests_equal(const CommitRequest &req1,
                             const CommitRequest &req2);

  /**
   * @brief Compare two preconditions for equality.
   * @param p1 First precondition
   * @param p2 Second precondition
   * @return true if equal, false otherwise
   */
  static bool preconditions_equal(const Precondition &p1,
                                  const Precondition &p2);

  /**
   * @brief Compare two operations for equality.
   * @param op1 First operation
   * @param op2 Second operation
   * @return true if equal, false otherwise
   */
  static bool operations_equal(const Operation &op1, const Operation &op2);
};