use rouille::{input::json_input, Request, Response};
use serde::Deserialize;
use serde_json::json;
use std::sync::Arc;

use super::helpers::{get_conn, json_error, require_auth};
use super::AppState;

pub fn list_thresholds(request: &Request, state: &Arc<AppState>) -> Response {
    let mut conn = match get_conn(state) {
        Ok(c) => c,
        Err(e) => return e,
    };
    if let Err(e) = require_auth(request, &mut conn) {
        return e;
    }

    match conn.query(
        "SELECT id, name, subscription_id, metric_type::text, threshold_value::float8, \
         comparison_operator, action, notification_channels::text, is_active, last_triggered::text \
         FROM alert_thresholds ORDER BY created_at DESC",
        &[],
    ) {
        Ok(rows) => {
            let thresholds: Vec<_> = rows
                .into_iter()
                .map(|row| {
                    let channels_str: Option<String> = row.get("notification_channels");
                    let channels: serde_json::Value = channels_str
                        .and_then(|s| serde_json::from_str(&s).ok())
                        .unwrap_or(json!(["email"]));
                    json!({
                        "id": row.get::<_, i32>("id"),
                        "name": row.get::<_, String>("name"),
                        "subscription_id": row.get::<_, Option<i32>>("subscription_id"),
                        "metric_type": row.get::<_, String>("metric_type"),
                        "threshold_value": row.get::<_, f64>("threshold_value"),
                        "comparison_operator": row.get::<_, String>("comparison_operator"),
                        "action": row.get::<_, String>("action"),
                        "notification_channels": channels,
                        "is_active": row.get::<_, bool>("is_active"),
                        "last_triggered": row.get::<_, Option<String>>("last_triggered"),
                    })
                })
                .collect();
            Response::json(&thresholds)
        }
        Err(e) => {
            log::error!("Database error: {}", e);
            json_error(500, "Database error")
        }
    }
}

pub fn create_threshold(request: &Request, state: &Arc<AppState>) -> Response {
    let threshold: sap_sync_backend::alert_system::AlertThresholdCreate = match json_input(request)
    {
        Ok(f) => f,
        Err(_) => return json_error(400, "Invalid JSON"),
    };

    let mut conn = match get_conn(state) {
        Ok(c) => c,
        Err(e) => return e,
    };
    if let Err(e) = require_auth(request, &mut conn) {
        return e;
    }

    let channels_json = serde_json::to_string(&threshold.notification_channels)
        .unwrap_or_else(|_| "[\"email\"]".to_string());
    let val_str = threshold.threshold_value.to_string();

    match conn.query_one(
        "INSERT INTO alert_thresholds \
         (name, subscription_id, metric_type, threshold_value, comparison_operator, action, notification_channels, is_active) \
         VALUES ($1, $2, $3::text::metric_type, $4::text::numeric, $5, $6, $7::text::jsonb, $8) RETURNING id",
        &[
            &threshold.name, &threshold.subscription_id, &threshold.metric_type,
            &val_str, &threshold.comparison_operator, &threshold.action,
            &channels_json, &threshold.is_active,
        ],
    ) {
        Ok(r) => Response::json(&json!({
            "id": r.get::<_, i32>(0),
            "name": threshold.name, "metric_type": threshold.metric_type,
            "threshold_value": threshold.threshold_value,
            "action": threshold.action, "is_active": threshold.is_active,
        })),
        Err(e) => {
            log::error!("Database error: {}", e);
            json_error(500, &format!("Database error: {}", e))
        }
    }
}

pub fn update_threshold(request: &Request, state: &Arc<AppState>, id: i32) -> Response {
    #[derive(Deserialize)]
    struct Form {
        name: String,
        subscription_id: Option<i32>,
        metric_type: String,
        threshold_value: f64,
        comparison_operator: String,
        action: String,
        is_active: Option<bool>,
    }

    let form: Form = match json_input(request) {
        Ok(f) => f,
        Err(_) => return json_error(400, "Invalid JSON"),
    };

    let mut conn = match get_conn(state) {
        Ok(c) => c,
        Err(e) => return e,
    };
    if let Err(e) = require_auth(request, &mut conn) {
        return e;
    }

    let val_str = form.threshold_value.to_string();
    let is_active = form.is_active.unwrap_or(true);

    match conn.execute(
        "UPDATE alert_thresholds SET name=$1, subscription_id=$2, \
         metric_type=$3::text::metric_type, threshold_value=$4::text::numeric, \
         comparison_operator=$5, action=$6, is_active=$7 WHERE id=$8",
        &[
            &form.name, &form.subscription_id, &form.metric_type,
            &val_str, &form.comparison_operator, &form.action, &is_active, &id,
        ],
    ) {
        Ok(0) => json_error(404, "Threshold not found"),
        Ok(_) => Response::json(&json!({"message": "Threshold updated"})),
        Err(e) => json_error(500, &format!("Update error: {}", e)),
    }
}

pub fn delete_threshold(request: &Request, state: &Arc<AppState>, id: i32) -> Response {
    let mut conn = match get_conn(state) {
        Ok(c) => c,
        Err(e) => return e,
    };
    if let Err(e) = require_auth(request, &mut conn) {
        return e;
    }

    match conn.execute("DELETE FROM alert_thresholds WHERE id = $1", &[&id]) {
        Ok(0) => json_error(404, "Threshold not found"),
        Ok(_) => Response::json(&json!({"message": "Threshold deleted"})),
        Err(e) => json_error(500, &format!("Delete error: {}", e)),
    }
}

pub fn get_history(request: &Request, state: &Arc<AppState>) -> Response {
    let mut conn = match get_conn(state) {
        Ok(c) => c,
        Err(e) => return e,
    };
    if let Err(e) = require_auth(request, &mut conn) {
        return e;
    }

    match conn.query(
        "SELECT ah.id, ah.threshold_id, at.name as threshold_name, \
         ah.actual_value::float8 as actual_value, ah.triggered_at::text as triggered_at, \
         ah.action_taken, ah.notification_sent \
         FROM alert_history ah \
         LEFT JOIN alert_thresholds at ON ah.threshold_id = at.id \
         ORDER BY ah.triggered_at DESC LIMIT 100",
        &[],
    ) {
        Ok(rows) => {
            let history: Vec<_> = rows
                .iter()
                .map(|row| {
                    json!({
                        "id": row.get::<_, i32>("id"),
                        "threshold_id": row.get::<_, i32>("threshold_id"),
                        "threshold_name": row.get::<_, Option<String>>("threshold_name").unwrap_or_default(),
                        "actual_value": row.get::<_, f64>("actual_value"),
                        "triggered_at": row.get::<_, Option<String>>("triggered_at"),
                        "action_taken": row.get::<_, Option<String>>("action_taken"),
                        "notification_sent": row.get::<_, bool>("notification_sent"),
                    })
                })
                .collect();
            Response::json(&history)
        }
        Err(e) => json_error(500, &format!("Query error: {}", e)),
    }
}
