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

async fn get_org_owner_email(pool: &PgPool, org_id: Uuid) -> Result<String, anyhow::Error> {
    let row = sqlx::query_as::<_, (String,)>(
        "SELECT email FROM users WHERE org_id = $1 AND role = 'owner' LIMIT 1"
    )
    .bind(org_id)
    .fetch_one(pool)
    .await?;
    Ok(row.0)
}

/// 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"
        );

        // Send Slack webhook alert
        if let Ok(slack_url) = std::env::var("SLACK_WEBHOOK_URL") {
            let payload = serde_json::json!({
                "blocks": [
                    {
                        "type": "header",
                        "text": { "type": "plain_text", "text": "💸 Cost Anomaly Detected" }
                    },
                    {
                        "type": "section",
                        "fields": [
                            { "type": "mrkdwn", "text": format!("*Org:* `{}`", org_id) },
                            { "type": "mrkdwn", "text": format!("*Current Hour:* ${:.4}", current_cost) },
                            { "type": "mrkdwn", "text": format!("*7-Day Avg:* ${:.4}", avg_cost) },
                            { "type": "mrkdwn", "text": format!("*Spike:* {:.1}x", spike_factor) }
                        ]
                    }
                ]
            });
            let client = reqwest::Client::new();
            if let Err(e) = client.post(&slack_url)
                .json(&payload)
                .send()
                .await
            {
                warn!(error = %e, "Failed to send Slack anomaly alert");
            }
        }

        // Send email alert via Resend
        if let (Ok(resend_key), Ok(owner_email)) = (
            std::env::var("RESEND_API_KEY"),
            get_org_owner_email(pg_pool, org_id).await,
        ) {
            let email_body = serde_json::json!({
                "from": "alerts@dd0c.dev",
                "to": [owner_email],
                "subject": format!("⚠️ dd0c/route: {:.1}x cost spike detected", spike_factor),
                "html": format!(
                    "<h2>Cost Anomaly Alert</h2>\
                     <p>Your LLM spend in the last hour (${:.4}) is <strong>{:.1}x</strong> your 7-day hourly average (${:.4}).</p>\
                     <p><a href=\"https://route.dd0c.dev/dashboard\">View Dashboard →</a></p>",
                    current_cost, spike_factor, avg_cost
                )
            });
            let client = reqwest::Client::new();
            if let Err(e) = client.post("https://api.resend.com/emails")
                .bearer_auth(&resend_key)
                .json(&email_body)
                .send()
                .await
            {
                warn!(error = %e, "Failed to send anomaly email");
            }
        }
    }

    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);
    }
}
