//! Athena
//!
//! A lightweight Database Gateway that proxies and executes queries across multiple backends
//! (Athena/ScyllaDB, PostgreSQL, and Supabase) with simple caching and routing.
//!
//! - Provides REST endpoints for executing SQL against supported drivers
//! - Proxies arbitrary requests while handling auth headers and basic response shaping
//! - Exposes a small set of utilities for driver execution and routing

// re-exports intentionally minimal in lib
use api::pipelines::PipelineDefinition;
use deadpool_postgres::Pool;
use moka::future::Cache;
use reqwest::Client;
use serde_json::Value;
use sqlx::postgres::PgPool;
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use std::time::Instant;
use tokio::sync::{OnceCell, Semaphore};

use crate::api::metrics::MetricsState;

#[cfg(feature = "deadpool_experimental")]
use crate::drivers::postgresql::deadpool_registry::DeadpoolPostgresRegistry;
use crate::drivers::postgresql::sqlx_driver::PostgresClientRegistry;

use crate::api::gateway::insert::InsertWindowCoordinator;
use crate::utils::client_stats_batcher::ClientStatsBatcher;
use crate::utils::request_logging::GatewayLogBatcher;

/// REST API surface, endpoints and request handlers.
pub mod api;
/// Reverse proxy that forwards requests to the configured target services.
pub mod bootstrap;
pub mod cli;
/// Athena client SDK with unified query helpers.
pub mod client;
/// Utils for configuration
pub mod config;
pub mod config_validation;
pub mod daemon;
/// Data access helpers and Supabase clients used by endpoints.
pub mod data;
/// Database driver integrations (Scylla/Athena, PostgreSQL, Supabase).
pub mod drivers;
/// Error processing and sanitization utilities.
pub mod error;
/// Parsers and helpers related to SQL processing.
pub mod parser;
pub mod provision_sql;
pub mod provisioning;

/// HTTP routing helpers and target URL determination.
pub mod webhooks;
pub mod wss;

pub mod features;

#[cfg(feature = "cdc")]
pub mod cdc;

/// Shared Actix application state.
pub struct AppState {
    /// Short‑lived response cache for JSON payloads.
    pub cache: Arc<Cache<String, Value>>,
    /// Non‑expiring cache for values that should persist across requests.
    pub immortal_cache: Arc<Cache<String, Value>>,
    /// Shared Reqwest client used by the proxy and endpoints.
    pub client: Client,
    /// Unix timestamp when the process started.
    pub process_start_time_seconds: i64,
    /// Monotonic clock used for uptime calculations.
    pub process_started_at: Instant,
    /// Registry of Postgres connections keyed by logical client name.
    pub pg_registry: Arc<PostgresClientRegistry>,
    /// Cache of Postgres pools created from X-JDBC-URL for direct connections.
    pub jdbc_pool_cache: Arc<Cache<String, PgPool>>,
    /// Experimental deadpool-backed registry of Postgres pools keyed by logical client name.
    #[cfg(feature = "deadpool_experimental")]
    pub deadpool_registry: Arc<DeadpoolPostgresRegistry>,
    /// Experimental deadpool-backed cache for direct JDBC pools (singleflight via OnceCell).
    #[cfg(feature = "deadpool_experimental")]
    pub jdbc_deadpool_cache: Arc<Cache<String, Arc<OnceCell<Pool>>>>,
    /// When true, gateway fetch routes force camelCase column names to snake_case.
    pub gateway_force_camel_case_to_snake_case: bool,
    /// When true, UUID-like filter values are explicitly cast to text when the
    /// generated SQL also casts the compared column to text.
    pub gateway_auto_cast_uuid_filter_values_to_text: bool,
    /// When true, `public.table` table references are normalized to `table`
    /// for information_schema lookups.
    pub gateway_allow_schema_names_prefixed_as_table_name: bool,
    /// Optional registry of prebuilt pipeline definitions by name.
    pub pipeline_registry: Option<Arc<HashMap<String, PipelineDefinition>>>,
    /// Optional Postgres client (by name) that receives gateway logs.
    pub logging_client_name: Option<String>,
    /// Optional Postgres client (by name) that stores API keys and auth configuration.
    pub gateway_auth_client_name: Option<String>,
    /// Logical Postgres client name used for gateway benchmark tooling (`cargo bench` E2E, etc.).
    ///
    /// Configured under `gateway.benchmark_client` and surfaced for health/metrics alongside
    /// logging and auth client configuration.
    pub gateway_benchmark_client_name: Option<String>,
    /// Gateway auth fail mode: `fail_closed` or `fail_open`.
    pub gateway_api_key_fail_mode: String,
    /// Whether direct JDBC connections to private/local hosts are allowed.
    pub gateway_jdbc_allow_private_hosts: bool,
    /// Optional host allowlist for direct JDBC connections.
    pub gateway_jdbc_allowed_hosts: Vec<String>,
    /// Gateway resilience: operation timeout in seconds.
    pub gateway_resilience_timeout_secs: u64,
    /// Gateway resilience: max retries for read operations on transient failures.
    pub gateway_resilience_read_max_retries: u32,
    /// Gateway resilience: initial backoff between retries in milliseconds.
    pub gateway_resilience_initial_backoff_ms: u64,
    /// Admission store backend: `memory` or `redis`.
    pub gateway_admission_store_backend: String,
    /// Admission store fail mode: `fail_closed` or `fail_open`.
    pub gateway_admission_store_fail_mode: String,
    /// Flag that enables the Prometheus exporter route when true.
    pub prometheus_metrics_enabled: bool,
    /// Shared in-process metrics registry.
    pub metrics_state: Arc<MetricsState>,
    /// Default insert execution window in ms (`0` = off unless header enables).
    pub gateway_insert_execution_window_ms: u64,

    pub gateway_insert_window_max_batch: usize,
    pub gateway_insert_window_max_queued: usize,
    pub gateway_insert_merge_deny_tables: HashSet<String>,
    /// Background coordinator for optional Postgres `/gateway/insert` windowing.
    pub insert_window_coordinator: Arc<InsertWindowCoordinator>,
    /// Batched `client_statistics` / `client_table_statistics` / `last_seen` writes for the logging pool.
    pub client_stats_batcher: Option<Arc<ClientStatsBatcher>>,
    /// Batched multi-row inserts for gateway request/operation logs.
    pub gateway_log_batcher: Option<Arc<GatewayLogBatcher>>,
    /// Limits concurrent best-effort background logging work that targets the shared logging pool.
    pub logging_task_limiter: Option<Arc<Semaphore>>,
}

/// Wrapper for the non‑expiring cache used by some endpoints.
pub struct ImmortalCache {
    /// Non‑expiring cache instance.
    pub cache: Arc<Cache<String, Value>>,
}

/// Miscellaneous utilities (logging, helpers).
pub mod utils;

pub use client::AthenaClient;
pub use client::backend::BackendType;
pub use client::backend::QueryResult;
pub use client::builder::AthenaClientBuilder;
pub use client::{Condition, ConditionOperator, OrderDirection};
pub use client::{
    Gateway, GatewayDeleteRequest, GatewayDriverRequest, GatewayFetchRequest, GatewayInsertRequest,
    GatewayOperation, GatewayPath, GatewayQueryResult, GatewayRequest, GatewayRequestFactory,
    GatewayRequestPayload, GatewayRoutes, GatewayRpcFilter, GatewayRpcFilterOperator,
    GatewayRpcRequest, GatewaySqlRequest, GatewayUpdateRequest, RpcBuilder, build_gateway_endpoint,
    request,
};

/// Backward-compatible route alias. Prefer `Gateway::FETCH_PATH`.
pub const GATEWAY_FETCH_PATH: &str = Gateway::FETCH_PATH;
/// Backward-compatible route alias. Prefer `Gateway::INSERT_PATH`.
pub const GATEWAY_INSERT_PATH: &str = Gateway::INSERT_PATH;
/// Backward-compatible route alias. Prefer `Gateway::UPDATE_PATH`.
pub const GATEWAY_UPDATE_PATH: &str = Gateway::UPDATE_PATH;
/// Backward-compatible route alias. Prefer `Gateway::DELETE_PATH`.
pub const GATEWAY_DELETE_PATH: &str = Gateway::DELETE_PATH;
/// Backward-compatible route alias. Prefer `Gateway::QUERY_PATH`.
pub const GATEWAY_QUERY_PATH: &str = Gateway::QUERY_PATH;
/// Backward-compatible route alias. Prefer `Gateway::SQL_PATH`.
pub const GATEWAY_SQL_PATH: &str = Gateway::SQL_PATH;
/// Backward-compatible route alias. Prefer `Gateway::RPC_PATH`.
pub const GATEWAY_RPC_PATH: &str = Gateway::RPC_PATH;
/// Backward-compatible route alias. Prefer `Gateway::LEGACY_SQL_PATH`.
pub const LEGACY_SQL_PATH: &str = Gateway::LEGACY_SQL_PATH;
