use rouille::{Request, Response};
use serde_json::json;
use std::sync::Arc;

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

pub fn get_logs(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 a.id, a.user_id, u.username, a.session_id, a.event, \
         host(a.ip_address) as ip, a.user_agent, a.metadata::text, a.timestamp::text \
         FROM session_audit_log a \
         LEFT JOIN users u ON u.id = a.user_id \
         ORDER BY a.timestamp DESC LIMIT 100",
        &[],
    ) {
        Ok(rows) => {
            let logs: Vec<_> = rows
                .into_iter()
                .map(|row| {
                    json!({
                        "id": row.get::<_, i32>(0),
                        "user_id": row.get::<_, i32>(1),
                        "username": row.get::<_, Option<String>>(2),
                        "session_id": row.get::<_, Option<String>>(3),
                        "event": row.get::<_, String>(4),
                        "ip_address": row.get::<_, Option<String>>(5),
                        "user_agent": row.get::<_, Option<String>>(6),
                        "metadata": serde_json::from_str::<serde_json::Value>(
                            &row.get::<_, String>(7)
                        ).unwrap_or(json!({})),
                        "timestamp": row.get::<_, String>(8),
                    })
                })
                .collect();
            Response::json(&logs)
        }
        Err(e) => {
            log::error!("Audit log query error: {}", e);
            json_error(500, "Database error")
        }
    }
}

pub fn get_sync_logs(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, sync_job_id, entity_type, entity_id, action, status, \
         error_message, metadata::text, timestamp::text, resolution_status \
         FROM sync_logs ORDER BY timestamp DESC LIMIT 100",
        &[],
    ) {
        Ok(rows) => {
            let logs: Vec<_> = rows
                .into_iter()
                .map(|row| {
                    json!({
                        "id": row.get::<_, i32>(0),
                        "sync_job_id": row.get::<_, i32>(1),
                        "entity_type": row.get::<_, String>(2),
                        "entity_id": row.get::<_, String>(3),
                        "action": row.get::<_, String>(4),
                        "status": row.get::<_, String>(5),
                        "error_message": row.get::<_, Option<String>>(6),
                        "metadata": serde_json::from_str::<serde_json::Value>(
                            &row.get::<_, String>(7)
                        ).unwrap_or(json!({})),
                        "timestamp": row.get::<_, String>(8),
                        "resolution_status": row.get::<_, Option<String>>(9),
                    })
                })
                .collect();
            Response::json(&logs)
        }
        Err(e) => {
            log::error!("Sync log query error: {}", e);
            json_error(500, "Database error")
        }
    }
}

pub fn export(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;
    }

    let rows = match conn.query(
        "SELECT a.id, u.username, a.event, host(a.ip_address) as ip, \
         a.user_agent, a.timestamp::text \
         FROM session_audit_log a \
         LEFT JOIN users u ON u.id = a.user_id \
         ORDER BY a.timestamp DESC LIMIT 1000",
        &[],
    ) {
        Ok(r) => r,
        Err(e) => return json_error(500, &format!("Query error: {}", e)),
    };

    let mut wtr = csv::Writer::from_writer(Vec::new());
    let _ = wtr.write_record(["ID", "User", "Event", "IP Address", "User Agent", "Timestamp"]);
    for row in &rows {
        let _ = wtr.write_record(&[
            row.get::<_, i32>(0).to_string(),
            row.get::<_, Option<String>>(1).unwrap_or_default(),
            row.get::<_, String>(2),
            row.get::<_, Option<String>>(3).unwrap_or_default(),
            row.get::<_, Option<String>>(4).unwrap_or_default(),
            row.get::<_, String>(5),
        ]);
    }
    let bytes = wtr.into_inner().unwrap_or_default();

    let date = chrono::Utc::now().format("%Y-%m-%d");
    Response::from_data("text/csv; charset=utf-8", bytes).with_additional_header(
        "Content-Disposition",
        format!("attachment; filename=\"audit-logs-{}.csv\"", date),
    )
}
