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(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, schedule_type, schedule_config::text, job_type, sync_direction, \
         is_active, last_run::text, next_run::text \
         FROM scheduled_syncs ORDER BY created_at DESC",
        &[],
    ) {
        Ok(rows) => {
            let syncs: Vec<_> = rows
                .into_iter()
                .map(|row| {
                    let config_str: String = row.get(3);
                    let config: serde_json::Value =
                        serde_json::from_str(&config_str).unwrap_or(json!({}));
                    json!({
                        "id": row.get::<_, i32>(0),
                        "name": row.get::<_, String>(1),
                        "schedule_type": row.get::<_, String>(2),
                        "schedule_config": config,
                        "job_type": row.get::<_, String>(4),
                        "sync_direction": row.get::<_, String>(5),
                        "is_active": row.get::<_, bool>(6),
                        "last_run": row.get::<_, Option<String>>(7),
                        "next_run": row.get::<_, Option<String>>(8),
                    })
                })
                .collect();
            Response::json(&syncs)
        }
        Err(e) => {
            log::error!("Database error: {}", e);
            json_error(500, "Database error")
        }
    }
}

pub fn create(request: &Request, state: &Arc<AppState>) -> Response {
    let data: serde_json::Value = 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 name = data.get("name").and_then(|v| v.as_str()).unwrap_or_default().to_string();
    let schedule_type = data.get("schedule_type").and_then(|v| v.as_str()).unwrap_or_default().to_string();
    let schedule_config = data.get("schedule_config").cloned().unwrap_or_default();
    let job_type = data.get("job_type").and_then(|v| v.as_str()).unwrap_or_default().to_string();
    let sync_direction = data.get("sync_direction").and_then(|v| v.as_str()).unwrap_or_default().to_string();
    let config_str = serde_json::to_string(&schedule_config).unwrap_or_default();

    match conn.query_one(
        "INSERT INTO scheduled_syncs \
         (name, schedule_type, schedule_config, job_type, sync_direction, \
          plesk_server_id, sap_server_id, is_active, created_at) \
         VALUES ($1, $2, $3::text::jsonb, $4, $5, $6, $7, true, NOW()) RETURNING id",
        &[&name, &schedule_type, &config_str, &job_type, &sync_direction, &None::<i32>, &None::<i32>],
    ) {
        Ok(r) => Response::json(&json!({"id": r.get::<_, i32>(0), "message": "Scheduled sync created successfully"})),
        Err(e) => {
            log::error!("Database error: {}", e);
            json_error(500, "Database error")
        }
    }
}

pub fn update(request: &Request, state: &Arc<AppState>, id: i32) -> Response {
    #[derive(Deserialize)]
    struct Form {
        name: Option<String>,
        schedule_type: Option<String>,
        job_type: Option<String>,
        sync_direction: Option<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;
    }

    match conn.execute(
        "UPDATE scheduled_syncs SET name=COALESCE($1, name), \
         schedule_type=COALESCE($2, schedule_type), job_type=COALESCE($3, job_type), \
         sync_direction=COALESCE($4, sync_direction), is_active=COALESCE($5, is_active) \
         WHERE id=$6",
        &[&form.name, &form.schedule_type, &form.job_type, &form.sync_direction, &form.is_active, &id],
    ) {
        Ok(0) => json_error(404, "Schedule not found"),
        Ok(_) => Response::json(&json!({"message": "Schedule updated"})),
        Err(e) => json_error(500, &format!("Update error: {}", e)),
    }
}

pub fn delete(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 scheduled_syncs WHERE id = $1", &[&id]) {
        Ok(0) => json_error(404, "Schedule not found"),
        Ok(_) => Response::json(&json!({"message": "Schedule deleted"})),
        Err(e) => json_error(500, &format!("Delete error: {}", e)),
    }
}
