use crate::AppState;
use axum::{
    extract::{Path, State},
    http::{HeaderMap, StatusCode},
    response::IntoResponse,
    routing::get,
    Json, Router,
};
use db::models::user::UserRepository;
use uuid::Uuid;

/// Internal, service-to-service routes (not exposed on the public API gateway).
/// Callers authenticate with the shared `X-AI-Service-Key` header, same as the
/// existing `/api/support/tickets/ai/create` endpoint.
pub fn router() -> Router<AppState> {
    Router::new().route("/{id}/llm-key", get(get_llm_key))
}

fn check_service_key(headers: &HeaderMap) -> bool {
    let expected_key = std::env::var("AI_SERVICE_KEY").unwrap_or_default();
    let provided_key = headers
        .get("X-AI-Service-Key")
        .and_then(|v| v.to_str().ok())
        .unwrap_or_default();
    !expected_key.is_empty() && provided_key == expected_key
}

/// GET /internal/users/{id}/llm-key
///
/// Returns this account's per-user LiteLLM virtual key, generating and
/// persisting one on the fly if it doesn't have one yet (covers accounts
/// created before this feature existed, or where generation failed at
/// registration time because LiteLLM was unreachable).
async fn get_llm_key(
    State(state): State<AppState>,
    headers: HeaderMap,
    Path(id): Path<Uuid>,
) -> impl IntoResponse {
    if !check_service_key(&headers) {
        return (
            StatusCode::UNAUTHORIZED,
            Json(serde_json::json!({ "error": "Invalid or missing AI service key" })),
        )
            .into_response();
    }

    match UserRepository::get_litellm_key(&state.pool, id).await {
        Ok(Some(key)) => (StatusCode::OK, Json(serde_json::json!({ "key": key }))).into_response(),
        Ok(None) => generate_and_store(&state, id).await,
        Err(e) => {
            tracing::error!(user_id = %id, error = %e, "Failed to look up LiteLLM key");
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(serde_json::json!({ "error": "Failed to look up LiteLLM key" })),
            )
                .into_response()
        }
    }
}

async fn generate_and_store(state: &AppState, user_id: Uuid) -> axum::response::Response {
    let client = match crate::ai::litellm::LiteLlmClient::new() {
        Ok(c) => c,
        Err(e) => {
            tracing::error!(error = %e, "LiteLLM client unavailable");
            return (
                StatusCode::BAD_GATEWAY,
                Json(serde_json::json!({ "error": "LiteLLM unavailable" })),
            )
                .into_response();
        }
    };

    match client.generate_key(user_id).await {
        Ok(key) => {
            if let Err(e) = UserRepository::set_litellm_key(&state.pool, user_id, &key).await {
                tracing::error!(user_id = %user_id, error = %e, "Failed to store LiteLLM key");
            }
            (StatusCode::OK, Json(serde_json::json!({ "key": key }))).into_response()
        }
        Err(e) => {
            tracing::error!(user_id = %user_id, error = %e, "Failed to generate LiteLLM key");
            (
                StatusCode::BAD_GATEWAY,
                Json(serde_json::json!({ "error": "Failed to generate LiteLLM key" })),
            )
                .into_response()
        }
    }
}
