use actix_web::{web, HttpResponse};
use serde_json::json;

use crate::api::athena_guard;
use crate::config::ScraperConfig;
use crate::data::scraper_overrides::{self, ScraperOverrideRow};
use crate::AppState;

fn spawn_resync_overrides(state: &web::Data<AppState>) {
    let Some(cli) = state.athena.clone() else {
        return;
    };
    let cache = state.scraper_overrides_cache.clone();
    tokio::spawn(async move {
        if let Err(e) = scraper_overrides::sync_scraper_overrides(cli.as_ref(), cache.as_ref()).await {
            tracing::warn!("scraper overrides resync: {}", e);
        }
    });
}

pub async fn list_scraper_overrides(state: web::Data<AppState>) -> HttpResponse {
    let Some(cli) = athena_guard::athena_client(state.get_ref()) else {
        return athena_guard::no_athena_response();
    };
    match scraper_overrides::list_overrides(cli).await {
        Ok(rows) => HttpResponse::Ok().json(
            rows
                .into_iter()
                .map(|r| {
                    json!({
                        "name": r.name,
                        "enabled": r.enabled,
                        "config": r.config,
                    })
                })
                .collect::<Vec<_>>(),
        ),
        Err(e) => HttpResponse::InternalServerError().json(json!({"error": e.to_string()})),
    }
}

pub async fn reload_scraper_overrides(state: web::Data<AppState>) -> HttpResponse {
    let Some(cli) = athena_guard::athena_client(state.get_ref()) else {
        return athena_guard::no_athena_response();
    };
    match scraper_overrides::sync_scraper_overrides(cli, state.scraper_overrides_cache.as_ref()).await {
        Ok(n) => HttpResponse::Ok().json(json!({ "count": n })),
        Err(e) => HttpResponse::InternalServerError().json(json!({"error": e.to_string()})),
    }
}

pub async fn post_scraper_override(
    state: web::Data<AppState>,
    body: web::Json<ScraperConfig>,
) -> HttpResponse {
    let Some(cli) = athena_guard::athena_client(state.get_ref()) else {
        return athena_guard::no_athena_response();
    };
    let cfg = body.into_inner();
    if cfg.name.trim().is_empty() {
        return HttpResponse::BadRequest().json(json!({"error": "config.name required"}));
    }
    let row = ScraperOverrideRow {
        name: cfg.name.clone(),
        enabled: true,
        config: cfg,
    };
    let created_name = row.name.clone();
    match scraper_overrides::insert_override(cli, &row).await {
        Ok(()) => {
            spawn_resync_overrides(&state);
            HttpResponse::Created().json(json!({ "name": created_name }))
        }
        Err(e) => HttpResponse::BadRequest().json(json!({"error": e.to_string()})),
    }
}

pub async fn put_scraper_override(
    state: web::Data<AppState>,
    path: web::Path<String>,
    body: web::Json<ScraperConfig>,
) -> HttpResponse {
    let Some(cli) = athena_guard::athena_client(state.get_ref()) else {
        return athena_guard::no_athena_response();
    };
    let name = path.into_inner();
    let mut cfg = body.into_inner();
    cfg.name = name.clone();
    let row = ScraperOverrideRow {
        name: name.clone(),
        enabled: true,
        config: cfg,
    };
    match scraper_overrides::update_override(cli, &name, &row).await {
        Ok(()) => {
            spawn_resync_overrides(&state);
            HttpResponse::Ok().json(json!({ "name": row.name }))
        }
        Err(e) => HttpResponse::BadRequest().json(json!({"error": e.to_string()})),
    }
}

pub async fn delete_scraper_override(state: web::Data<AppState>, path: web::Path<String>) -> HttpResponse {
    let Some(cli) = athena_guard::athena_client(state.get_ref()) else {
        return athena_guard::no_athena_response();
    };
    let name = path.into_inner();
    match scraper_overrides::delete_override(cli, &name).await {
        Ok(()) => {
            spawn_resync_overrides(&state);
            HttpResponse::NoContent().finish()
        }
        Err(e) => HttpResponse::BadRequest().json(json!({"error": e.to_string()})),
    }
}
