pub mod collector;

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::time::Duration;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RequestMetric {
    pub timestamp: DateTime<Utc>,
    pub client_id: usize,
    pub service: ServiceType,
    pub latency: Duration,
    pub status: RequestStatus,
    pub error_type: Option<String>,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum ServiceType {
    Trading,
    Backtesting,
    MlTraining,
    Gateway,
}

impl std::fmt::Display for ServiceType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ServiceType::Trading => write!(f, "Trading"),
            ServiceType::Backtesting => write!(f, "Backtesting"),
            ServiceType::MlTraining => write!(f, "ML Training"),
            ServiceType::Gateway => write!(f, "Gateway"),
        }
    }
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum RequestStatus {
    Success,
    Error,
    Timeout,
    RateLimited,
    CircuitBreakerOpen,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AggregatedMetrics {
    pub total_requests: u64,
    pub successful_requests: u64,
    pub failed_requests: u64,
    pub timeout_requests: u64,
    pub rate_limited_requests: u64,
    pub circuit_breaker_requests: u64,
    pub duration: Duration,
    pub requests_per_second: f64,
    pub error_rate_pct: f64,
    pub latency_stats: LatencyStats,
    pub per_service_stats: std::collections::HashMap<ServiceType, ServiceStats>,
    pub system_metrics: Option<SystemMetrics>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LatencyStats {
    pub min_ms: f64,
    pub max_ms: f64,
    pub mean_ms: f64,
    pub p50_ms: f64,
    pub p90_ms: f64,
    pub p95_ms: f64,
    pub p99_ms: f64,
    pub p99_9_ms: f64,
    pub stddev_ms: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServiceStats {
    pub total_requests: u64,
    pub successful_requests: u64,
    pub error_rate_pct: f64,
    pub latency_stats: LatencyStats,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemMetrics {
    pub cpu_usage_pct: f64,
    pub memory_used_mb: f64,
    pub memory_total_mb: f64,
    pub memory_usage_pct: f64,
    pub circuit_breaker_trips: u64,
    pub rate_limit_hits: u64,
    pub connection_pool_utilization_pct: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoadTestReport {
    pub test_name: String,
    pub start_time: DateTime<Utc>,
    pub end_time: DateTime<Utc>,
    pub config: TestConfig,
    pub metrics: AggregatedMetrics,
    pub time_series: Vec<TimeSeriesPoint>,
    pub capacity_recommendation: Option<CapacityRecommendation>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TestConfig {
    pub num_clients: usize,
    pub duration_secs: u64,
    pub test_type: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TimeSeriesPoint {
    pub timestamp: DateTime<Utc>,
    pub rps: f64,
    pub p99_latency_ms: f64,
    pub error_rate_pct: f64,
    pub active_clients: usize,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CapacityRecommendation {
    pub max_sustainable_clients: usize,
    pub max_sustainable_rps: f64,
    pub bottleneck_identified: Option<String>,
    pub recommendation: String,
}
