use actix_web::{web, HttpResponse};
use serde_json::json;
use std::collections::HashMap;

use crate::api::athena_guard;
use crate::data::http_profiles;
use crate::http_profile::HttpClientProfile;
use crate::AppState;

fn refresh_http_profile_cache(state: &web::Data<AppState>) {
    let Some(cli) = state.athena.clone() else {
        return;
    };
    let cache = state.http_profile_cache.clone();
    tokio::spawn(async move {
        if let Ok(list) = http_profiles::list_profiles(cli.as_ref()).await {
            let mut map = HashMap::new();
            for p in list {
                if p.enabled {
                    map.insert(p.name.clone(), p);
                }
            }
            if let Ok(mut g) = cache.write() {
                *g = map;
            }
        }
    });
}

pub async fn list_http_profiles(state: web::Data<AppState>) -> HttpResponse {
    let Some(cli) = athena_guard::athena_client(state.get_ref()) else {
        return athena_guard::no_athena_response();
    };
    match http_profiles::list_profiles(cli).await {
        Ok(rows) => HttpResponse::Ok().json(
            rows
                .into_iter()
                .map(|p| p.masked_for_api())
                .collect::<Vec<_>>(),
        ),
        Err(e) => HttpResponse::InternalServerError().json(json!({"error": e.to_string()})),
    }
}

pub async fn get_http_profile(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 http_profiles::get_profile_by_name(cli.as_ref(), &name).await {
        Ok(Some(p)) => HttpResponse::Ok().json(p.masked_for_api()),
        Ok(None) => HttpResponse::NotFound().json(json!({"error": "profile not found"})),
        Err(e) => HttpResponse::InternalServerError().json(json!({"error": e.to_string()})),
    }
}

pub async fn post_http_profile(
    state: web::Data<AppState>,
    body: web::Json<HttpClientProfile>,
) -> HttpResponse {
    let Some(cli) = athena_guard::athena_client(state.get_ref()) else {
        return athena_guard::no_athena_response();
    };
    let p = body.into_inner();
    if p.name.trim().is_empty() {
        return HttpResponse::BadRequest().json(json!({"error": "name required"}));
    }
    match http_profiles::insert_profile(cli.as_ref(), &p).await {
        Ok(()) => {
            refresh_http_profile_cache(&state);
            HttpResponse::Created().json(p.masked_for_api())
        }
        Err(e) => HttpResponse::BadRequest().json(json!({"error": e.to_string()})),
    }
}

pub async fn put_http_profile(
    state: web::Data<AppState>,
    path: web::Path<String>,
    body: web::Json<HttpClientProfile>,
) -> 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 p = body.into_inner();
    p.name = name.clone();
    match http_profiles::update_profile(cli.as_ref(), &name, &p).await {
        Ok(()) => {
            refresh_http_profile_cache(&state);
            HttpResponse::Ok().json(p.masked_for_api())
        }
        Err(e) => HttpResponse::BadRequest().json(json!({"error": e.to_string()})),
    }
}

pub async fn delete_http_profile(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 http_profiles::disable_profile(cli.as_ref(), &name).await {
        Ok(()) => {
            refresh_http_profile_cache(&state);
            HttpResponse::NoContent().finish()
        }
        Err(e) => HttpResponse::BadRequest().json(json!({"error": e.to_string()})),
    }
}
