use sqlx::PgPool;
use uuid::Uuid;
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};

// TODO: Define Map struct (id, server_id, name, file_path, size_bytes, uploaded_at)
// TODO: Define MapRotation struct (id, server_id, map_ids, current_index, auto_rotate)

/// Map performance metrics for analytics.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MapPerformanceMetrics {
    pub map_id: Uuid,
    pub map_name: String,
    pub seed: Option<i32>,
    pub times_used: i64,
    pub avg_players: f64,
    pub peak_players: i32,
    pub unique_players: Option<i64>, // Phase 2.3 (requires player session tracking)
    pub effectiveness_score: f64,
}

/// Map analytics summary response.
#[derive(Debug, Clone, Serialize)]
pub struct MapAnalyticsSummary {
    pub maps: Vec<MapPerformanceMetrics>,
    pub best_performing_map: Option<String>,
    pub rotation_effectiveness: f64,
}

/// Upload/register a new custom map.
pub async fn create_map(pool: &PgPool, server_id: Uuid, name: &str, file_path: &str, size_bytes: i64) -> Result<Uuid> {
    todo!()
}

/// Get all maps for a server.
pub async fn get_maps(pool: &PgPool, server_id: Uuid) -> Result<()> {
    todo!()
}

/// Fetch a single map by ID.
pub async fn get_map_by_id(pool: &PgPool, map_id: Uuid) -> Result<()> {
    todo!()
}

/// Delete a map record (and its associated file reference).
pub async fn delete_map(pool: &PgPool, map_id: Uuid) -> Result<()> {
    todo!()
}

/// Get the current map rotation configuration for a server.
pub async fn get_map_rotation(pool: &PgPool, server_id: Uuid) -> Result<()> {
    todo!()
}

/// Update the map rotation (set map order, current index, toggle auto-rotate).
pub async fn update_map_rotation(pool: &PgPool, server_id: Uuid, map_ids: &[Uuid], auto_rotate: bool) -> Result<()> {
    todo!()
}

/// Get map analytics for a license over a time range (in days).
/// Returns effectiveness metrics: avg players, peak players, times used, effectiveness score.
pub async fn get_map_analytics(
    pool: &PgPool,
    license_id: Uuid,
    days: i64,
) -> Result<MapAnalyticsSummary> {
    // Query map performance: JOIN server_stats with map_library to get metrics per map
    let map_metrics: Vec<MapPerformanceMetrics> = sqlx::query_as::<_, (Uuid, String, Option<i32>, i64, f64, i32)>(
        "SELECT
            m.id as map_id,
            m.display_name as map_name,
            m.seed,
            COUNT(DISTINCT DATE_TRUNC('day', s.recorded_at)) as times_used,
            AVG(s.player_count)::FLOAT8 as avg_players,
            MAX(s.player_count) as peak_players
         FROM map_library m
         INNER JOIN server_stats s ON s.map_id = m.id
         WHERE m.license_id = $1
           AND s.recorded_at >= NOW() - ($2 || ' days')::INTERVAL
         GROUP BY m.id, m.display_name, m.seed
         ORDER BY avg_players DESC",
    )
    .bind(license_id)
    .bind(days)
    .fetch_all(pool)
    .await
    .context("Failed to query map analytics")?
    .into_iter()
    .map(|(map_id, map_name, seed, times_used, avg_players, peak_players)| {
        // Calculate effectiveness score: weighted avg of player count and peak (0-100 scale)
        // Formula: (avg_players / peak_players) * 70 + (peak_players / max_server_slots) * 30
        // Simplified version: (avg_players / peak_players if > 0 else 0) * 100
        let effectiveness_score = if peak_players > 0 {
            ((avg_players / peak_players as f64) * 100.0).min(100.0)
        } else {
            0.0
        };

        MapPerformanceMetrics {
            map_id,
            map_name,
            seed,
            times_used,
            avg_players,
            peak_players,
            unique_players: None, // Phase 2.3
            effectiveness_score,
        }
    })
    .collect();

    // Determine best performing map (highest avg players)
    let best_performing_map = map_metrics
        .iter()
        .max_by(|a, b| a.avg_players.partial_cmp(&b.avg_players).unwrap())
        .map(|m| m.map_name.clone());

    // Calculate overall rotation effectiveness (avg of all map effectiveness scores)
    let rotation_effectiveness = if !map_metrics.is_empty() {
        map_metrics.iter().map(|m| m.effectiveness_score).sum::<f64>() / map_metrics.len() as f64
    } else {
        0.0
    };

    Ok(MapAnalyticsSummary {
        maps: map_metrics,
        best_performing_map,
        rotation_effectiveness,
    })
}

/// Get player count trends per map over wipe cycles.
/// Returns time-series data grouped by map and wipe.
pub async fn get_map_population_trends(
    pool: &PgPool,
    license_id: Uuid,
) -> Result<Vec<(Uuid, String, String, f64)>> {
    // Query: JOIN wipe_history with server_stats to get avg player count per map per wipe
    let trends: Vec<(Uuid, String, String, f64)> = sqlx::query_as(
        "SELECT
            m.id as map_id,
            m.display_name as map_name,
            w.started_at::TEXT as wipe_date,
            AVG(s.player_count)::FLOAT8 as avg_players
         FROM map_library m
         INNER JOIN wipe_history w ON w.map_id = m.id
         INNER JOIN server_stats s ON s.license_id = w.license_id
            AND s.recorded_at >= w.started_at
            AND s.recorded_at < COALESCE(w.completed_at, NOW())
         WHERE m.license_id = $1
           AND w.started_at IS NOT NULL
         GROUP BY m.id, m.display_name, w.started_at
         ORDER BY w.started_at ASC",
    )
    .bind(license_id)
    .fetch_all(pool)
    .await
    .context("Failed to query map population trends")?;

    Ok(trends)
}
