# grantflow/tests/test_integration_portfolio_quality_exports.py

import gzip

import json


from fastapi.testclient import TestClient


from grantflow.api import runtime_state

from grantflow.api.app import app

client = TestClient(app)


def test_portfolio_quality_export_endpoint_returns_csv():
    response = client.get(
        "/portfolio/quality/export",
        params={
            "donor_id": "usaid",
            "status": "done",
            "grounding_risk_level": "high",
            "finding_status": "open",
            "finding_severity": "high",
            "format": "csv",
        },
    )
    assert response.status_code == 200
    assert response.headers["content-type"].startswith("text/csv")
    disposition = response.headers.get("content-disposition", "")
    assert "attachment;" in disposition
    assert "grantflow_portfolio_quality_usaid_done" in disposition

    body = response.text
    assert body.startswith("field,value\n")
    assert "filters.donor_id,usaid" in body
    assert "filters.status,done" in body
    assert "filters.grounding_risk_level,high" in body
    assert "filters.finding_status,open" in body
    assert "filters.finding_severity,high" in body
    assert "severity_weighted_risk_score," in body
    assert "priority_signal_breakdown.high_severity_findings_total.weight," in body
    assert "citations.architect_claim_support_rate," in body


def test_portfolio_quality_export_csv_flattens_donor_advisory_label_mix():
    runtime_state.JOB_STORE.set(
        "portfolio-quality-export-job-seeded",
        {
            "status": "done",
            "hitl_enabled": True,
            "state": {
                "donor_id": "usaid",
                "quality_score": 8.0,
                "critic_score": 7.5,
                "needs_revision": False,
                "critic_notes": {
                    "fatal_flaws": [
                        {
                            "finding_id": "seed-f1",
                            "severity": "medium",
                            "status": "open",
                            "section": "toc",
                            "source": "llm",
                            "label": "CAUSAL_LINK_DETAIL",
                        }
                    ],
                    "llm_advisory_diagnostics": {
                        "advisory_applies": False,
                        "advisory_candidate_count": 2,
                        "advisory_rejected_reason": "grounding_threshold_not_met",
                        "candidate_label_counts": {
                            "CAUSAL_LINK_DETAIL": 1,
                            "BASELINE_TARGET_MISSING": 1,
                        },
                    },
                },
                "citations": [
                    {"stage": "architect", "citation_type": "rag_low_confidence", "citation_confidence": 0.2},
                    {"stage": "architect", "citation_type": "rag_claim_support", "citation_confidence": 0.9},
                ],
            },
            "job_events": [
                {
                    "event_id": "pqx1",
                    "ts": "2026-02-24T12:00:00+00:00",
                    "type": "status_changed",
                    "to_status": "accepted",
                },
                {
                    "event_id": "pqx2",
                    "ts": "2026-02-24T12:00:01+00:00",
                    "type": "status_changed",
                    "to_status": "running",
                },
                {"event_id": "pqx3", "ts": "2026-02-24T12:00:10+00:00", "type": "status_changed", "to_status": "done"},
            ],
        },
    )

    response = client.get("/portfolio/quality/export", params={"donor_id": "usaid", "status": "done", "format": "csv"})
    assert response.status_code == 200
    body = response.text
    assert "donor_weighted_risk_breakdown.usaid.llm_advisory_rejected_label_counts.CAUSAL_LINK_DETAIL," in body
    assert "donor_weighted_risk_breakdown.usaid.llm_advisory_rejected_label_counts.BASELINE_TARGET_MISSING," in body


def test_portfolio_quality_export_endpoint_supports_json_and_gzip():
    json_resp = client.get("/portfolio/quality/export", params={"donor_id": "usaid", "format": "json"})
    assert json_resp.status_code == 200
    assert json_resp.headers["content-type"].startswith("application/json")
    json_disposition = json_resp.headers.get("content-disposition", "")
    assert "grantflow_portfolio_quality_usaid.json" in json_disposition
    payload = json_resp.json()
    assert "severity_weighted_risk_score" in payload
    assert "priority_signal_breakdown" in payload

    toc_csv_resp = client.get(
        "/portfolio/quality/export",
        params={"donor_id": "usaid", "toc_text_risk_level": "high", "format": "csv"},
    )
    assert toc_csv_resp.status_code == 200
    assert toc_csv_resp.headers["content-type"].startswith("text/csv")
    toc_csv_text = toc_csv_resp.text
    assert "filters.toc_text_risk_level,high" in toc_csv_text

    toc_json_resp = client.get(
        "/portfolio/quality/export",
        params={"donor_id": "usaid", "toc_text_risk_level": "high", "format": "json"},
    )
    assert toc_json_resp.status_code == 200
    assert toc_json_resp.headers["content-type"].startswith("application/json")
    toc_payload = toc_json_resp.json()
    assert toc_payload["filters"]["donor_id"] == "usaid"
    assert toc_payload["filters"]["toc_text_risk_level"] == "high"

    mel_csv_resp = client.get(
        "/portfolio/quality/export",
        params={"donor_id": "usaid", "mel_risk_level": "medium", "format": "csv"},
    )
    assert mel_csv_resp.status_code == 200
    assert mel_csv_resp.headers["content-type"].startswith("text/csv")
    mel_csv_text = mel_csv_resp.text
    assert "filters.mel_risk_level,medium" in mel_csv_text

    mel_json_resp = client.get(
        "/portfolio/quality/export",
        params={"donor_id": "usaid", "mel_risk_level": "medium", "format": "json"},
    )
    assert mel_json_resp.status_code == 200
    mel_payload = mel_json_resp.json()
    assert mel_payload["filters"]["donor_id"] == "usaid"
    assert mel_payload["filters"]["mel_risk_level"] == "medium"

    csv_gzip_resp = client.get(
        "/portfolio/quality/export", params={"donor_id": "usaid", "format": "csv", "gzip": "true"}
    )
    assert csv_gzip_resp.status_code == 200
    assert csv_gzip_resp.headers["content-type"].startswith("application/gzip")
    csv_gzip_disposition = csv_gzip_resp.headers.get("content-disposition", "")
    assert "grantflow_portfolio_quality_usaid.csv.gz" in csv_gzip_disposition
    csv_text = gzip.decompress(csv_gzip_resp.content).decode("utf-8")
    assert csv_text.startswith("field,value\n")
    assert "severity_weighted_risk_score," in csv_text

    json_gzip_resp = client.get(
        "/portfolio/quality/export", params={"donor_id": "usaid", "format": "json", "gzip": "true"}
    )
    assert json_gzip_resp.status_code == 200
    assert json_gzip_resp.headers["content-type"].startswith("application/gzip")
    json_gzip_disposition = json_gzip_resp.headers.get("content-disposition", "")
    assert "grantflow_portfolio_quality_usaid.json.gz" in json_gzip_disposition
    json_text = gzip.decompress(json_gzip_resp.content).decode("utf-8")
    parsed = json.loads(json_text)
    assert "filters" in parsed
    assert parsed["filters"]["donor_id"] == "usaid"
