use crate::common::TestServer;
use serde_json::json;

#[tokio::test]
async fn stats_overview_reflects_inserted_data() {
    let server = TestServer::start().await;

    // Add a target
    server
        .post(
            "/api/v1/targets",
            &json!({
                "name": "stats-repo",
                "target_type": "web_app",
                "artifacts": [{ "kind": "git_repo", "source_ref": "https://github.com/example/stats-repo.git", "branch": "main" }],
            }),
        )
        .await;

    // Insert findings directly
    let mongodb_uri = std::env::var("TEST_MONGODB_URI")
        .unwrap_or_else(|_| "mongodb://root:example@localhost:27017/?authSource=admin".into());
    let client = mongodb::Client::with_uri_str(&mongodb_uri).await.unwrap();
    let db = client.database(&server.db_name());
    let now = mongodb::bson::DateTime::now();

    for (title, severity) in [
        ("Critical Bug", "critical"),
        ("High Bug", "high"),
        ("Medium Bug", "medium"),
        ("Low Bug", "low"),
    ] {
        db.collection::<mongodb::bson::Document>("findings")
            .insert_one(mongodb::bson::doc! {
                "repo_id": "test-repo-id",
                "fingerprint": format!("fp-{title}"),
                "scanner": "test",
                "scan_type": "sast",
                "title": title,
                "description": "desc",
                "severity": severity,
                "status": "open",
                "created_at": now,
                "updated_at": now,
            })
            .await
            .unwrap();
    }

    let resp = server.get("/api/v1/stats/overview").await;
    assert_eq!(resp.status(), 200);

    let body: serde_json::Value = resp.json().await.unwrap();
    let data = &body["data"];
    assert_eq!(data["repositories"], 1);
    assert_eq!(data["total_findings"], 4);
    assert_eq!(data["critical"], 1);
    assert_eq!(data["high"], 1);

    server.cleanup().await;
}

#[tokio::test]
async fn stats_update_after_finding_status_change() {
    let server = TestServer::start().await;

    // Insert a finding
    let mongodb_uri = std::env::var("TEST_MONGODB_URI")
        .unwrap_or_else(|_| "mongodb://root:example@localhost:27017/?authSource=admin".into());
    let client = mongodb::Client::with_uri_str(&mongodb_uri).await.unwrap();
    let db = client.database(&server.db_name());
    let now = mongodb::bson::DateTime::now();

    let result = db
        .collection::<mongodb::bson::Document>("findings")
        .insert_one(mongodb::bson::doc! {
            "repo_id": "repo-1",
            "fingerprint": "fp-stats-test",
            "scanner": "test",
            "scan_type": "sast",
            "title": "Stats Test Finding",
            "description": "desc",
            "severity": "high",
            "status": "open",
            "created_at": now,
            "updated_at": now,
        })
        .await
        .unwrap();
    let finding_id = result.inserted_id.as_object_id().unwrap().to_hex();

    // Stats should show 1 finding
    let resp = server.get("/api/v1/stats/overview").await;
    let body: serde_json::Value = resp.json().await.unwrap();
    assert_eq!(body["data"]["total_findings"], 1);

    // Mark it as resolved
    server
        .patch(
            &format!("/api/v1/findings/{finding_id}/status"),
            &json!({ "status": "resolved" }),
        )
        .await;

    // The finding still exists (status changed, not deleted)
    let resp = server.get("/api/v1/stats/overview").await;
    let body: serde_json::Value = resp.json().await.unwrap();
    // total_findings counts all findings regardless of status
    assert_eq!(body["data"]["total_findings"], 1);

    server.cleanup().await;
}
