use sqlx::PgPool;
use tracing::{info, warn};
use uuid::Uuid;

/// Simple threshold-based anomaly detection.
/// Compares last hour's spend to the 7-day hourly average.
/// If current hour > 3x average, fire an alert.
pub async fn check_anomalies(ts_pool: &PgPool, pg_pool: &PgPool) -> anyhow::Result<()> {
    // Get orgs with recent activity
    let orgs = sqlx::query_as::<_, (Uuid,)>(
        "SELECT DISTINCT org_id FROM request_events WHERE time >= now() - interval '1 hour'"
    )
    .fetch_all(ts_pool)
    .await?;

    for (org_id,) in &orgs {
        check_org_anomaly(ts_pool, pg_pool, *org_id).await?;
    }

    Ok(())
}

async fn check_org_anomaly(ts_pool: &PgPool, pg_pool: &PgPool, org_id: Uuid) -> anyhow::Result<()> {
    // Last hour's cost
    let current = sqlx::query_as::<_, (f64,)>(
        "SELECT COALESCE(SUM(cost_actual), 0)::float8
         FROM request_events
         WHERE org_id = $1 AND time >= now() - interval '1 hour'"
    )
    .bind(org_id)
    .fetch_one(ts_pool)
    .await?;

    // 7-day hourly average
    let avg = sqlx::query_as::<_, (f64,)>(
        "SELECT COALESCE(AVG(hourly_cost), 0)::float8 FROM (
            SELECT SUM(cost_actual) as hourly_cost
            FROM request_events
            WHERE org_id = $1 AND time >= now() - interval '7 days' AND time < now() - interval '1 hour'
            GROUP BY time_bucket('1 hour', time)
        ) sub"
    )
    .bind(org_id)
    .fetch_one(ts_pool)
    .await?;

    let current_cost = current.0;
    let avg_cost = avg.0;

    // 3x threshold
    if avg_cost > 0.0 && current_cost > avg_cost * 3.0 {
        let spike_factor = current_cost / avg_cost;
        warn!(
            org_id = %org_id,
            current_cost = format!("${:.4}", current_cost),
            avg_cost = format!("${:.4}", avg_cost),
            spike = format!("{:.1}x", spike_factor),
            "Cost anomaly detected"
        );

        // TODO: Send Slack webhook alert
        // TODO: Send email alert to org owner
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    #[test]
    fn anomaly_threshold_3x() {
        let avg = 10.0;
        let current = 35.0;
        assert!(current > avg * 3.0);
    }

    #[test]
    fn no_anomaly_under_threshold() {
        let avg = 10.0;
        let current = 25.0;
        assert!(current <= avg * 3.0);
    }
}
