use axum::Json;
use mongodb::bson::doc;

use super::dto::*;
use compliance_core::models::ScanRun;
use compliance_core::tenant_ctx::TenantCtx;

#[tracing::instrument(skip_all)]
pub async fn health() -> Json<serde_json::Value> {
    Json(serde_json::json!({ "status": "ok" }))
}

/// GET /api/v1/settings/ssh-public-key — the agent's SSH deploy public key,
/// for adding as a read-only deploy key on private git targets.
#[tracing::instrument(skip_all)]
pub async fn get_ssh_public_key(
    axum::extract::Extension(agent): AgentExt,
) -> Result<Json<serde_json::Value>, axum::http::StatusCode> {
    let public_path = format!("{}.pub", agent.config.ssh_key_path);
    let public_key =
        std::fs::read_to_string(&public_path).map_err(|_| axum::http::StatusCode::NOT_FOUND)?;
    Ok(Json(serde_json::json!({ "public_key": public_key.trim() })))
}

#[tracing::instrument(skip_all)]
pub async fn stats_overview(
    axum::extract::Extension(agent): AgentExt,
    tenant: TenantCtx,
) -> ApiResult<OverviewStats> {
    let db = tenant_db(&agent, &tenant).await?;
    let db = &db;

    let total_repositories = db
        .onboarded_targets()
        .count_documents(doc! {})
        .await
        .unwrap_or(0);
    let total_findings = db.findings().count_documents(doc! {}).await.unwrap_or(0);
    let critical_findings = db
        .findings()
        .count_documents(doc! { "severity": "critical" })
        .await
        .unwrap_or(0);
    let high_findings = db
        .findings()
        .count_documents(doc! { "severity": "high" })
        .await
        .unwrap_or(0);
    let medium_findings = db
        .findings()
        .count_documents(doc! { "severity": "medium" })
        .await
        .unwrap_or(0);
    let low_findings = db
        .findings()
        .count_documents(doc! { "severity": "low" })
        .await
        .unwrap_or(0);
    let total_sbom_entries = db
        .sbom_entries()
        .count_documents(doc! {})
        .await
        .unwrap_or(0);
    let total_cve_alerts = db.cve_alerts().count_documents(doc! {}).await.unwrap_or(0);
    let total_issues = db
        .tracker_issues()
        .count_documents(doc! {})
        .await
        .unwrap_or(0);

    let recent_scans: Vec<ScanRun> = match db
        .scan_runs()
        .find(doc! {})
        .sort(doc! { "started_at": -1 })
        .limit(10)
        .await
    {
        Ok(cursor) => collect_cursor_async(cursor).await,
        Err(e) => {
            tracing::warn!("Failed to fetch recent scans: {e}");
            Vec::new()
        }
    };

    Ok(Json(ApiResponse {
        data: OverviewStats {
            total_repositories,
            total_findings,
            critical_findings,
            high_findings,
            medium_findings,
            low_findings,
            total_sbom_entries,
            total_cve_alerts,
            total_issues,
            recent_scans,
        },
        total: None,
        page: None,
    }))
}
