import json

from grantflow.api import runtime_state
from grantflow.tests.review_traceability_helpers import client, generate_done_job


def test_status_includes_draft_versions_traceability():
    job_id, status = generate_done_job({"project": "Livelihoods", "country": "Kenya"})

    state = status["state"]
    assert state.get("toc_validation", {}).get("valid") is True
    assert state.get("toc_validation", {}).get("schema_name")
    assert state.get("architect_retrieval", {}).get("namespace")
    assert state.get("architect_retrieval", {}).get("namespace_normalized")
    assert "hits_count" in (state.get("architect_retrieval") or {})
    retrieval_hits = (state.get("architect_retrieval") or {}).get("hits")
    if isinstance(retrieval_hits, list) and retrieval_hits:
        assert "doc_id" in retrieval_hits[0]
        assert "retrieval_rank" in retrieval_hits[0]
        assert "retrieval_confidence" in retrieval_hits[0]
        assert "retrieval_distance" in retrieval_hits[0]
    assert state.get("toc_generation_meta", {}).get("engine")
    assert isinstance(state.get("toc_draft", {}).get("validation"), dict)
    assert isinstance(state.get("toc_draft", {}).get("architect_retrieval"), dict)
    versions = state.get("draft_versions")
    assert isinstance(versions, list)
    assert len(versions) >= 2
    sections = {v.get("section") for v in versions}
    assert "toc" in sections
    assert "logframe" in sections
    assert "job_events" not in status

    events_resp = client.get(f"/status/{job_id}/events")
    assert events_resp.status_code == 200
    events_body = events_resp.json()
    assert events_body["job_id"] == job_id
    assert events_body["event_count"] >= 3
    event_types = [e["type"] for e in events_body["events"]]
    assert "status_changed" in event_types
    statuses = [e.get("to_status") for e in events_body["events"] if e["type"] == "status_changed"]
    assert "accepted" in statuses
    assert "running" in statuses
    assert "done" in statuses


def test_status_events_export_endpoint_supports_csv_json_and_gzip():
    job_id = "events-export-job-1"
    runtime_state.JOB_STORE.set(
        job_id,
        {
            "status": "done",
            "state": {"donor_id": "usaid"},
            "job_events": [
                {
                    "event_id": "evt-1",
                    "ts": "2026-03-01T10:00:00+00:00",
                    "type": "status_changed",
                    "from_status": "accepted",
                    "to_status": "running",
                    "status": "running",
                },
                {
                    "event_id": "evt-2",
                    "ts": "2026-03-01T10:00:10+00:00",
                    "type": "review_workflow_sla_recomputed",
                    "actor": "qa",
                    "total_updated_count": 3,
                    "applied_finding_sla_hours": {"high": 12, "medium": 48, "low": 96},
                },
                {
                    "event_id": "evt-3",
                    "ts": "2026-03-01T10:00:20+00:00",
                    "type": "status_changed",
                    "from_status": "running",
                    "to_status": "done",
                    "status": "done",
                },
            ],
        },
    )

    export_csv = client.get(f"/status/{job_id}/events/export", params={"format": "csv"})
    assert export_csv.status_code == 200
    assert "text/csv" in (export_csv.headers.get("content-type") or "")
    assert f"grantflow_job_events_{job_id}.csv" in (export_csv.headers.get("content-disposition") or "")
    assert "event_id,ts,type,status,from_status,to_status,checkpoint_id" in export_csv.text
    assert "review_workflow_sla_recomputed" in export_csv.text
    assert "applied_finding_sla_hours" in export_csv.text

    export_json = client.get(f"/status/{job_id}/events/export", params={"format": "json"})
    assert export_json.status_code == 200
    assert "application/json" in (export_json.headers.get("content-type") or "")
    export_json_body = json.loads(export_json.text)
    assert export_json_body["job_id"] == job_id
    assert export_json_body["event_count"] == 3
    assert export_json_body["events"][1]["type"] == "review_workflow_sla_recomputed"

    export_csv_gzip = client.get(
        f"/status/{job_id}/events/export",
        params={"format": "csv", "gzip": "true"},
    )
    assert export_csv_gzip.status_code == 200
    assert "application/gzip" in (export_csv_gzip.headers.get("content-type") or "")
    assert (export_csv_gzip.headers.get("content-disposition") or "").endswith('.csv.gz"')
