//! Core Persistence Layer for Foxhunt HFT Trading System
//!
//! This module provides the main database connectivity and data persistence
//! infrastructure for high-frequency trading operations.
//!
//! # Architecture
//!
//! ``text
//! ┌─────────────────────────────────────────────────────────────────┐
//! │                    Foxhunt Persistence Stack                    │
//! ├─────────────────────────────────────────────────────────────────┤
//! │  Trading Layer: Order Management, Position Tracking            │
//! ├─────────────────────────────────────────────────────────────────┤
//! │  Persistence Layer: PostgreSQL, InfluxDB, Redis, ClickHouse    │
//! ├─────────────────────────────────────────────────────────────────┤
//! │  Connection Management: Pools, Health Checks, Failover         │
//! ├─────────────────────────────────────────────────────────────────┤
//! │  Performance Layer: Sub-1ms timeouts, Connection prewarming    │
//! └─────────────────────────────────────────────────────────────────┘
//! ``

pub mod backup;
pub mod clickhouse;
pub mod health;
pub mod influxdb;
pub mod migrations;
pub mod postgres;
pub mod redis;

#[cfg(test)]
mod redis_integration_test;

// DO NOT RE-EXPORT - Use explicit imports at usage sites

use serde::{Deserialize, Serialize};
use std::time::Duration;
use thiserror::Error;

// Import required config types from submodules
use crate::persistence::backup::create_full_backup;
use crate::persistence::clickhouse::{ClickHouseClient, ClickHouseConfig, ClickHouseError};
use crate::persistence::health::{HealthStatus, PersistenceHealth};
use crate::persistence::influxdb::{InfluxClient, InfluxConfig, InfluxError};
use crate::persistence::migrations::run_pending_migrations;
use crate::persistence::postgres::{PostgresConfig, PostgresError, PostgresPool};
use crate::persistence::redis::{RedisConfig, RedisError, RedisPool};

/// Core persistence configuration for all database systems
#[derive(Debug, Clone, Deserialize, Serialize)]
/// PersistenceConfig
///
/// Auto-generated documentation placeholder - enhance with specifics
pub struct PersistenceConfig {
    /// `PostgreSQL` configuration for main trading data
    pub postgres: PostgresConfig,
    /// `InfluxDB` configuration for time-series metrics
    pub influx: InfluxConfig,
    /// `Redis` configuration for caching and session data
    pub redis: RedisConfig,
    /// `ClickHouse` configuration for analytics (optional)
    pub clickhouse: Option<ClickHouseConfig>,
    /// Global persistence settings
    pub global: GlobalPersistenceConfig,
}

/// Global persistence settings affecting all database connections
#[derive(Debug, Clone, Deserialize, Serialize)]
/// GlobalPersistenceConfig
///
/// Auto-generated documentation placeholder - enhance with specifics
pub struct GlobalPersistenceConfig {
    /// Environment (development, staging, production)
    pub environment: String,
    /// Enable detailed query logging for performance analysis
    pub enable_query_logging: bool,
    /// Enable connection pool monitoring
    pub enable_pool_monitoring: bool,
    /// Enable automatic health checks
    pub enable_health_checks: bool,
    /// Health check interval in seconds
    pub health_check_interval_seconds: u64,
    /// Maximum allowed query latency in microseconds for `HFT` operations
    pub max_query_latency_micros: u64,
}

impl Default for GlobalPersistenceConfig {
    fn default() -> Self {
        Self {
            environment: "development".to_owned(),
            enable_query_logging: true,
            enable_pool_monitoring: true,
            enable_health_checks: true,
            health_check_interval_seconds: 30,
            max_query_latency_micros: 800, // <1ms for HFT
        }
    }
}

/// Unified error type for all persistence operations
#[derive(Debug, Error)]
/// PersistenceError
///
/// Auto-generated documentation placeholder - enhance with specifics
pub enum PersistenceError {
    #[error("PostgreSQL error: {0}")]
    // Postgres variant
    Postgres(#[from] PostgresError),
    #[error("InfluxDB error: {0}")]
    // Influx variant
    Influx(#[from] InfluxError),
    #[error("Redis error: {0}")]
    // Redis variant
    Redis(#[from] RedisError),
    #[error("ClickHouse error: {0}")]
    // ClickHouse variant
    ClickHouse(#[from] ClickHouseError),
    #[error("Configuration error: {0}")]
    // Configuration variant
    Configuration(String),
    #[error("Health check failed: {0}")]
    // HealthCheck variant
    HealthCheck(String),
    #[error(
        "Performance violation: {operation} took {actual_micros}\u{3bc}s, max allowed {max_micros}\u{3bc}s"
    )]
    PerformanceViolation {
        operation: String,
        actual_micros: u64,
        max_micros: u64,
    },
}

/// Main persistence manager coordinating all database connections
#[derive(Debug)]
pub struct PersistenceManager {
    postgres: PostgresPool,
    influx: InfluxClient,
    redis: RedisPool,
    clickhouse: Option<ClickHouseClient>,
    config: PersistenceConfig,
    health: PersistenceHealth,
}

impl PersistenceManager {
    /// Initialize the persistence manager with all database connections
    pub async fn new(config: PersistenceConfig) -> Result<Self, PersistenceError> {
        // Initialize PostgreSQL connection pool for main trading data
        let postgres = PostgresPool::new(config.postgres.clone()).await?;

        // Initialize InfluxDB client for time-series data
        let influx = InfluxClient::new(config.influx.clone()).await?;

        // Initialize Redis connection pool for caching
        let redis = RedisPool::new(config.redis.clone()).await?;

        // Initialize ClickHouse client if configured
        let clickhouse = if let Some(ch_config) = &config.clickhouse {
            Some(ClickHouseClient::new(ch_config.clone()).await?)
        } else {
            // None variant
            None
        };

        // Initialize health monitoring
        let health = PersistenceHealth::new(
            config.global.enable_health_checks,
            Duration::from_secs(config.global.health_check_interval_seconds),
        );

        Ok(Self {
            postgres,
            influx,
            redis,
            clickhouse,
            config,
            health,
        })
    }

    /// Get `PostgreSQL` connection pool
    pub const fn postgres(&self) -> &PostgresPool {
        &self.postgres
    }

    /// Get `InfluxDB` client
    pub const fn influx(&self) -> &InfluxClient {
        &self.influx
    }

    /// Get `Redis` connection pool
    pub const fn redis(&self) -> &RedisPool {
        &self.redis
    }

    /// Get `ClickHouse` client (if configured)
    pub const fn clickhouse(&self) -> Option<&ClickHouseClient> {
        self.clickhouse.as_ref()
    }

    /// Get persistence configuration
    pub const fn config(&self) -> &PersistenceConfig {
        &self.config
    }

    /// Check health of all database connections
    pub async fn health_check(&self) -> Result<HealthStatus, PersistenceError> {
        self.health
            .check_all_systems(
                &self.postgres,
                &self.influx,
                &self.redis,
                self.clickhouse.as_ref(),
            )
            .await
            .map_err(|e| PersistenceError::Configuration(format!("Health check failed: {}", e)))
    }

    /// Run database migrations on `PostgreSQL`
    pub async fn run_migrations(&self) -> Result<(), PersistenceError> {
        run_pending_migrations(self.postgres.pool())
            .await
            .map(|_| ())
            .map_err(|e| PersistenceError::Configuration(format!("Migration failed: {}", e)))
    }

    /// Perform backup operations
    pub async fn backup(&self) -> Result<(), PersistenceError> {
        create_full_backup(&self.config)
            .await
            .map(|_| ())
            .map_err(|e| PersistenceError::Configuration(format!("Backup failed: {}", e)))
    }

    /// Get performance metrics from all systems
    pub async fn get_performance_metrics(&self) -> Result<PersistenceMetrics, PersistenceError> {
        Ok(PersistenceMetrics {
            postgres: self.postgres.get_metrics().await?,
            influx: self.influx.get_metrics().await?,
            redis: self.redis.get_metrics().await?,
            clickhouse: if let Some(ch) = &self.clickhouse {
                Some(ch.get_metrics().await?)
            } else {
                // None variant
                None
            },
        })
    }
}

/// Performance metrics for all persistence systems
#[derive(Debug, Clone, Serialize, Deserialize)]
/// PersistenceMetrics
///
/// Auto-generated documentation placeholder - enhance with specifics
pub struct PersistenceMetrics {
    /// Postgres
    pub postgres: postgres::PostgresMetrics,
    /// Influx
    pub influx: influxdb::InfluxMetrics,
    /// `Redis`
    pub redis: redis::RedisMetrics,
    /// Clickhouse
    pub clickhouse: Option<clickhouse::ClickHouseMetrics>,
}

/// `Result` type for persistence operations
pub type PersistenceResult<T> = Result<T, PersistenceError>;
