use axum::{extract::State, routing::get, Json, Router};
use serde::Serialize;
use serde_json::{json, Value};

#[derive(Serialize)]
pub struct DashboardMetricsResponse {
    kpis: Vec<Value>,
    trend_series: Vec<Value>,
    rev_series: Vec<Value>,
    lead_rows: Vec<Value>,
}

pub fn router() -> Router<crate::AppState> {
    Router::new().route("/metrics", get(get_metrics))
}

async fn get_metrics(State(state): State<crate::AppState>) -> Json<DashboardMetricsResponse> {
    let total_users: i64 = sqlx::query_scalar::<_, i64>("SELECT COUNT(*) FROM users")
        .fetch_one(&state.pool)
        .await
        .unwrap_or(0);

    let active_companies: i64 = sqlx::query_scalar::<_, i64>(
        "SELECT COUNT(*) FROM company_profiles WHERE status = 'APPROVED'",
    )
    .fetch_one(&state.pool)
    .await
    .unwrap_or(0);

    let open_leads: i64 = sqlx::query_scalar::<_, i64>(
        "SELECT COUNT(*) FROM leads WHERE status = 'PENDING_APPROVAL' OR status = 'APPROVED'",
    )
    .fetch_one(&state.pool)
    .await
    .unwrap_or(0);

    let pending_approvals: i64 = sqlx::query_scalar::<_, i64>(
        r#"
        SELECT COUNT(*) FROM (
            SELECT id FROM user_role_profiles WHERE status = 'PENDING_APPROVAL'
        ) sub
        "#,
    )
    .fetch_one(&state.pool)
    .await
    .unwrap_or(0);

    let total_revenue: i64 = sqlx::query_scalar::<_, i64>(
        "SELECT COALESCE(SUM(amount_inr), 0) FROM payments WHERE status = 'SUCCESS'",
    )
    .fetch_one(&state.pool)
    .await
    .unwrap_or(0);

    let kpis = vec![
        json!({ "id": "users", "title": "Total Users", "value": format!("{}", total_users), "trend": "-", "trendUp": true }),
        json!({ "id": "companies", "title": "Active Companies", "value": format!("{}", active_companies), "trend": "-", "trendUp": true }),
        json!({ "id": "leads", "title": "Open Leads", "value": format!("{}", open_leads), "trend": "-", "trendUp": true }),
        json!({ "id": "approvals", "title": "Pending Approvals", "value": format!("{}", pending_approvals), "trend": "-", "trendUp": false }),
        json!({ "id": "revenue", "title": "Total Revenue", "value": format!("₹{:.0}", total_revenue as f64 / 100.0), "trend": "-", "trendUp": true }),
    ];

    // User registrations per day (last 7 days)
    #[derive(sqlx::FromRow)]
    struct TrendRow {
        day_name: Option<String>,
        count: Option<i64>,
    }

    let trend_rows = sqlx::query_as::<_, TrendRow>(
        r#"
        SELECT TO_CHAR(DATE_TRUNC('day', created_at), 'Dy') AS day_name,
               COUNT(*) AS count
        FROM users
        WHERE created_at >= NOW() - INTERVAL '7 days'
        GROUP BY DATE_TRUNC('day', created_at), day_name
        ORDER BY DATE_TRUNC('day', created_at)
        "#,
    )
    .fetch_all(&state.pool)
    .await
    .unwrap_or_default();

    let trend_series: Vec<Value> = trend_rows
        .into_iter()
        .map(|r| json!({ "name": r.day_name.unwrap_or_default(), "Users": r.count.unwrap_or(0) }))
        .collect();

    // Revenue per week (last 4 weeks)
    #[derive(sqlx::FromRow)]
    struct RevRow {
        week_name: Option<String>,
        total: Option<i64>,
    }

    let rev_rows = sqlx::query_as::<_, RevRow>(
        r#"
        SELECT TO_CHAR(DATE_TRUNC('week', created_at), '"Week" W') AS week_name,
               COALESCE(SUM(amount_inr), 0) AS total
        FROM payments
        WHERE status = 'SUCCESS' AND created_at >= NOW() - INTERVAL '28 days'
        GROUP BY DATE_TRUNC('week', created_at), week_name
        ORDER BY DATE_TRUNC('week', created_at)
        "#,
    )
    .fetch_all(&state.pool)
    .await
    .unwrap_or_default();

    let rev_series: Vec<Value> = rev_rows
        .into_iter()
        .map(|r| json!({ "name": r.week_name.unwrap_or_default(), "Revenue": r.total.unwrap_or(0) }))
        .collect();

    // Recent open leads
    #[derive(sqlx::FromRow)]
    struct LeadRow {
        id: uuid::Uuid,
        title: String,
        status: String,
        created_at: chrono::DateTime<chrono::Utc>,
        requester_name: Option<String>,
    }

    let recent_leads = sqlx::query_as::<_, LeadRow>(
        r#"
        SELECT r.id, r.title, r.status, r.created_at,
                CONCAT(u.first_name, ' ', u.last_name) AS requester_name
        FROM leads r
        LEFT JOIN users u ON u.id = r.created_by_user_id
        WHERE r.status IN ('PENDING_APPROVAL', 'APPROVED')
        ORDER BY r.created_at DESC
        LIMIT 5
        "#,
    )
    .fetch_all(&state.pool)
    .await
    .unwrap_or_default();

    let lead_rows: Vec<Value> = recent_leads
        .into_iter()
        .map(|r| {
            json!({
                "id": format!("L-{}", &r.id.to_string()[..8].to_uppercase()),
                "client": r.requester_name.unwrap_or_else(|| "Unknown".to_string()),
                "service": r.title,
                "status": r.status,
                "date": r.created_at.format("%b %d, %Y").to_string()
            })
        })
        .collect();

    Json(DashboardMetricsResponse {
        kpis,
        trend_series,
        rev_series,
        lead_rows,
    })
}
