#pragma once

#include "commit_request.hpp"

/**
 * @brief Abstract interface for commit request parsers.
 *
 * This interface defines how parsers should interact with CommitRequest
 * objects. Parsers are responsible for reading serialized data in various
 * formats and populating CommitRequest objects with arena-allocated memory.
 *
 * The interface supports both one-shot parsing (for complete data buffers)
 * and streaming parsing (for incremental data processing). This allows
 * efficient handling of network protocols where data may arrive in chunks.
 */
struct CommitRequestParser {
public:
  /**
   * @brief Status returned by streaming parse operations.
   */
  enum class [[nodiscard]] ParseStatus {
    Incomplete, ///< Parser needs more data to complete parsing
    Complete,   ///< Successfully parsed a complete commit request
    Error       ///< Parse error occurred (check get_parse_error() for details)
  };

  /**
   * @brief Result type for one-shot parsing operations.
   */
  enum class [[nodiscard]] ParseResult {
    Success,      ///< Parsing completed successfully
    InvalidJson,  ///< Invalid JSON format or structure
    MissingField, ///< Required field missing from input
    InvalidField, ///< Field value is invalid or malformed
    OutOfMemory   ///< Arena allocation failed
  };

  virtual ~CommitRequestParser() = default;

  /**
   * @brief Parse data into a CommitRequest object (one-shot parsing).
   * @param request The CommitRequest object to populate
   * @param data Pointer to the data buffer
   * @param len Length of the data in bytes
   * @return ParseResult indicating success or specific error type
   */
  virtual ParseResult parse(CommitRequest &request, char *data,
                            int64_t len) = 0;

  /**
   * @brief Initialize streaming parsing.
   * @param request The CommitRequest object to populate
   * @return true if initialization succeeded, false otherwise
   */
  virtual bool begin_streaming_parse(CommitRequest &request) = 0;

  /**
   * @brief Parse additional data incrementally.
   * @param data Pointer to the data buffer
   * @param len Length of the data. Must be non-zero.
   * @return ParseStatus indicating current parse state
   */
  virtual ParseStatus parse_chunk(char *data, int64_t len) = 0;

  /**
   * @brief Finish streaming parse (call when no more data is available).
   * @return ParseStatus indicating final parse result
   */
  virtual ParseStatus finish_streaming_parse() = 0;

  /**
   * @brief Check if there was a parse error.
   * @return true if there was a parse error
   */
  bool has_parse_error() const { return get_parse_error(); };

  /**
   * @brief Get the parse error message if there was an error.
   * @return Error message string, or nullptr if no error
   */
  virtual const char *get_parse_error() const = 0;
};
