#pragma once

#include <chrono>
#include <optional>
#include <string>

namespace weaseldb {

/**
 * @brief Configuration settings for the WeaselDB server component.
 */
struct ServerConfig {
  /// IP address to bind the server to (default: localhost)
  std::string bind_address = "127.0.0.1";
  /// TCP port number for the server to listen on
  int port = 8080;
  /// Unix socket path (if specified, takes precedence over TCP)
  std::string unix_socket_path;
  /// Maximum size in bytes for incoming HTTP requests (default: 1MB)
  int64_t max_request_size_bytes = 1024 * 1024;
  /// Number of I/O threads for handling connections and network events
  int io_threads = 1;
  /// Number of epoll instances to reduce epoll_ctl contention (default:
  /// io_threads, max: io_threads)
  int epoll_instances = 1;
  /// Event batch size for epoll processing
  int event_batch_size = 32;
  /// Maximum number of concurrent connections (0 = unlimited)
  int max_connections = 50000;
  /// Buffer size for reading from socket connections (default: 16KB)
  int read_buffer_size = 16 * 1024;
};

/**
 * @brief Configuration settings for commit processing and validation.
 */
struct CommitConfig {
  /// Minimum required length for request_id to ensure sufficient entropy
  int min_request_id_length = 20;
  /// How long to retain request IDs for duplicate detection
  std::chrono::hours request_id_retention_hours{24};
  /// Minimum number of commit versions to retain request IDs for
  int64_t request_id_retention_versions = 100000000;
};

/**
 * @brief Configuration settings for subscription streaming functionality.
 */
struct SubscriptionConfig {
  /// Maximum buffer size for unconsumed subscription data before backpressure
  int64_t max_buffer_size_bytes = 10 * 1024 * 1024;
  /// Interval between keepalive comments in subscription streams
  std::chrono::seconds keepalive_interval{30};
};

/**
 * @brief Top-level configuration container for all WeaselDB settings.
 */
struct Config {
  ServerConfig server; ///< Server networking and request handling settings
  CommitConfig commit; ///< Commit processing and validation settings
  SubscriptionConfig subscription; ///< Subscription streaming settings
};

/**
 * @brief TOML configuration file parser for WeaselDB settings.
 *
 * This class provides static methods to parse TOML configuration files
 * and strings into structured Config objects. It uses the toml11 library
 * for TOML parsing and provides fallback to default values for any
 * missing configuration options.
 *
 * @example
 * ```cpp
 * // Load from file
 * auto config = ConfigParser::load_from_file("config.toml");
 * if (config) {
 *   std::cout << "Server port: " << config->server.port << std::endl;
 * }
 *
 * // Parse from string
 * std::string toml = "[server]\nport = 9090\n";
 * auto config2 = ConfigParser::parse_toml_string(toml);
 * ```
 */
struct ConfigParser {
public:
  /**
   * @brief Load configuration from a TOML file.
   * @param file_path Path to the TOML configuration file
   * @return Config object if successful, nullopt if parsing failed
   */
  static std::optional<Config> load_from_file(const std::string &file_path);

  /**
   * @brief Parse configuration from a TOML string.
   * @param toml_content TOML-formatted configuration string
   * @return Config object if successful, nullopt if parsing failed
   */
  static std::optional<Config>
  parse_toml_string(const std::string &toml_content);

  /**
   * @brief Validate configuration values are within reasonable bounds.
   *
   * This function performs comprehensive validation of all configuration
   * parameters and writes detailed diagnostic messages to stderr for any
   * validation failures or warnings encountered.
   *
   * @param config Configuration object to validate
   * @return true if configuration is valid, false otherwise
   * @note Validation errors and warnings are written to stderr
   */
  static bool validate_config(const Config &config);

private:
  // Generic configuration parsing utilities
  template <typename T>
  static void parse_field(const auto &section, const std::string &field_name,
                          T &target);

  template <typename Rep, typename Period>
  static void parse_duration_field(const auto &section,
                                   const std::string &field_name,
                                   std::chrono::duration<Rep, Period> &target);

  static void parse_section(const auto &toml_data,
                            const std::string &section_name, auto parse_func);

  static void parse_server_config(const auto &toml_data, ServerConfig &config);
  static void parse_commit_config(const auto &toml_data, CommitConfig &config);
  static void parse_subscription_config(const auto &toml_data,
                                        SubscriptionConfig &config);
};

} // namespace weaseldb
