use std::collections::HashMap;
use std::sync::{Arc, RwLock};

use anyhow::{anyhow, Result};
use athena_rs::client::AthenaClient;
use athena_rs::OrderDirection;

use crate::http_profile::HttpClientProfile;

const TABLE: &str = "http_request_profiles";

pub async fn list_profiles(client: &AthenaClient) -> Result<Vec<HttpClientProfile>> {
    let res = client
        .fetch(TABLE)
        .where_neq("name", "")
        .order_by("name", OrderDirection::Asc)
        .limit(1000)
        .execute()
        .await
        .map_err(|e| anyhow!("fetch {}: {}", TABLE, e))?;
    let mut out = Vec::new();
    for row in &res.rows {
        out.push(HttpClientProfile::from_athena_row(row)?);
    }
    Ok(out)
}

pub async fn get_profile_by_name(client: &AthenaClient, name: &str) -> Result<Option<HttpClientProfile>> {
    let res = client
        .fetch(TABLE)
        .where_eq("name", name)
        .limit(1)
        .execute()
        .await
        .map_err(|e| anyhow!("fetch profile: {}", e))?;
    let Some(row) = res.rows.first() else {
        return Ok(None);
    };
    Ok(Some(HttpClientProfile::from_athena_row(row)?))
}

pub async fn insert_profile(client: &AthenaClient, profile: &HttpClientProfile) -> Result<()> {
    HttpClientProfile::validate_proxy_url(profile.proxy_url.as_deref())?;
    client
        .insert(TABLE)
        .payload(profile.to_insert_payload(true))
        .execute()
        .await
        .map_err(|e| anyhow!("insert profile: {}", e))?;
    Ok(())
}

pub async fn update_profile(client: &AthenaClient, name: &str, profile: &HttpClientProfile) -> Result<()> {
    HttpClientProfile::validate_proxy_url(profile.proxy_url.as_deref())?;
    client
        .update(TABLE)
        .where_eq("name", name)
        .payload(profile.to_update_payload())
        .execute()
        .await
        .map_err(|e| anyhow!("update profile: {}", e))?;
    Ok(())
}

pub async fn delete_profile(client: &AthenaClient, name: &str) -> Result<()> {
    client
        .delete(TABLE)
        .where_eq("name", name)
        .execute()
        .await
        .map_err(|e| anyhow!("delete profile: {}", e))?;
    Ok(())
}

pub async fn resolve_profile_cached(
    athena: Option<&Arc<AthenaClient>>,
    cache: &Arc<RwLock<HashMap<String, HttpClientProfile>>>,
    name: &str,
) -> Option<HttpClientProfile> {
    if let Ok(g) = cache.read() {
        if let Some(p) = g.get(name) {
            return Some(p.clone());
        }
    }
    let cli = athena?;
    let Ok(Some(p)) = get_profile_by_name(cli.as_ref(), name).await else {
        return None;
    };
    if !p.enabled {
        return None;
    }
    if let Ok(mut g) = cache.write() {
        g.insert(name.to_string(), p.clone());
    }
    Some(p)
}

/// Soft-disable (keeps row for history).
pub async fn disable_profile(client: &AthenaClient, name: &str) -> Result<()> {
    let payload = serde_json::json!({
        "enabled": false,
        "updated_at": chrono::Utc::now().to_rfc3339(),
    });
    client
        .update(TABLE)
        .where_eq("name", name)
        .payload(payload)
        .execute()
        .await
        .map_err(|e| anyhow!("disable profile: {}", e))?;
    Ok(())
}
