#pragma once

#include <array>
#include <optional>
#include <string_view>

/**
 * @brief Defines all HTTP routes supported by the WeaselDB server.
 */
enum class HttpRoute {
  GetVersion,
  PostCommit,
  GetSubscribe,
  GetStatus,
  PutRetention,
  GetRetention,
  DeleteRetention,
  GetMetrics,
  GetOk,
  NotFound
};

/**
 * @brief Defines unique keys for all known URL and query parameters in the API.
 * @note This allows for O(1) lookup of parameter values in a fixed-size array.
 */
enum class ApiParameterKey {
  // --- Query Parameters ---
  RequestId,
  MinVersion,

  // --- URL Parameters ---
  PolicyId,

  // --- Sentinel for array size ---
  Count
};

/**
 * @brief A fixed-size array for storing parsed parameter values from a URL.
 *
 * It is indexed by the ApiParameterKey enum. The value is a string_view into
 * the original URL string, making lookups allocation-free.
 */
using ApiParameters = std::array<std::optional<std::string_view>,
                                 static_cast<size_t>(ApiParameterKey::Count)>;

/**
 * @brief Result codes for URL parsing operations.
 */
enum class [[nodiscard]] ParseResult { Success, MalformedEncoding };

/**
 * @brief Contains the complete, structured result of a successful URL parse.
 *
 * This struct is the output of the ApiUrlParser and contains everything
 * a handler needs to process a request, with no further parsing required.
 */
struct RouteMatch {
  /**
   * @brief The specific API endpoint that was matched.
   */
  HttpRoute route;

  /**
   * @brief A fixed-size array containing all parsed URL and query parameters.
   */
  ApiParameters params;
};

/**
 * @brief A parser that matches a URL against the fixed WeaselDB API.
 *
 * This class provides a single static method to parse a URL and method
 * into a structured RouteMatch object. It is designed to be a high-performance,
 * allocation-free parser with a simple interface.
 */
class ApiUrlParser {
public:
  /**
   * @brief Parses a URL and HTTP method against the known WeaselDB API
   * endpoints.
   *
   * **Mutates in place**: This function performs RFC 3986 percent-decoding
   * directly on the provided URL buffer. Path segments are decoded according
   * to RFC 3986, while query parameters follow
   * application/x-www-form-urlencoded rules (+ → space, then %XX → bytes).
   *
   * @param method The HTTP method of the request.
   * @param url_data Mutable buffer containing the URL (will be modified
   * in-place).
   * @param url_length Length of the URL data in bytes.
   * @param out_match Output parameter for the parsed route and parameters.
   * @return ParseResult::Success on successful parsing,
   * ParseResult::MalformedEncoding if the URL contains invalid percent-encoding
   * sequences.
   * @note On success, string_view parameters in out_match point into the
   *       decoded url_data buffer and remain valid while url_data is unchanged.
   * @note On error, url_data contents are undefined and should not be used.
   */
  [[nodiscard]] static ParseResult parse(std::string_view method,
                                         char *url_data, int url_length,
                                         RouteMatch &out_match);
};
