# grantflow/tests/test_integration_portfolio_sla_hotspots.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_review_workflow_sla_hotspots_endpoint_aggregates_jobs_and_filters():
    donor = "portfolio_review_workflow_sla_hotspots_test_donor"
    runtime_state.JOB_STORE.set(
        "portfolio-review-workflow-sla-hotspots-job-1",
        {
            "status": "done",
            "hitl_enabled": True,
            "generate_preflight": {"warning_level": "medium", "risk_level": "medium"},
            "state": {
                "donor_id": donor,
                "critic_notes": {
                    "fatal_flaws": [
                        {
                            "finding_id": "prwh-1",
                            "code": "TOC_SCHEMA_INVALID",
                            "severity": "high",
                            "section": "toc",
                            "status": "open",
                            "updated_at": "2026-02-27T10:00:00+00:00",
                            "due_at": "2026-02-25T10:00:00+00:00",
                            "sla_hours": 24,
                        }
                    ]
                },
            },
            "review_comments": [
                {
                    "comment_id": "prwh-comment-1",
                    "ts": "2026-02-27T10:05:00+00:00",
                    "section": "toc",
                    "status": "open",
                    "message": "Need stronger assumptions.",
                    "linked_finding_id": "prwh-1",
                    "due_at": "2026-02-25T11:00:00+00:00",
                    "sla_hours": 24,
                }
            ],
            "job_events": [
                {
                    "event_id": "prwh-evt-1",
                    "ts": "2026-02-27T10:00:00+00:00",
                    "type": "critic_finding_status_changed",
                    "finding_id": "prwh-1",
                    "status": "open",
                    "section": "toc",
                    "severity": "high",
                }
            ],
        },
    )
    runtime_state.JOB_STORE.set(
        "portfolio-review-workflow-sla-hotspots-job-2",
        {
            "status": "done",
            "hitl_enabled": True,
            "generate_preflight": {"warning_level": "low", "risk_level": "low"},
            "state": {
                "donor_id": donor,
                "critic_notes": {
                    "fatal_flaws": [
                        {
                            "finding_id": "prwh-2",
                            "code": "MEL_BASELINE_MISSING",
                            "severity": "medium",
                            "section": "toc",
                            "status": "acknowledged",
                            "updated_at": "2026-02-20T11:00:00+00:00",
                            "due_at": "2026-02-26T10:00:00+00:00",
                            "sla_hours": 72,
                        }
                    ]
                },
            },
            "review_comments": [
                {
                    "comment_id": "prwh-comment-2",
                    "ts": "2026-02-27T11:05:00+00:00",
                    "section": "toc",
                    "status": "open",
                    "message": "Need indicator source.",
                    "linked_finding_id": "prwh-2",
                    "due_at": "2026-02-26T12:00:00+00:00",
                    "sla_hours": 72,
                }
            ],
            "job_events": [
                {
                    "event_id": "prwh-evt-2",
                    "ts": "2026-02-27T11:00:00+00:00",
                    "type": "critic_finding_status_changed",
                    "finding_id": "prwh-2",
                    "status": "acknowledged",
                    "section": "toc",
                    "severity": "medium",
                }
            ],
        },
    )

    response = client.get(
        "/portfolio/review-workflow/sla/hotspots",
        params={
            "donor_id": donor,
            "status": "done",
            "hitl_enabled": "true",
            "finding_section": "toc",
            "overdue_after_hours": 12,
            "hotspot_kind": "comment",
            "min_overdue_hours": 24,
            "top_limit": 5,
        },
    )
    assert response.status_code == 200
    body = response.json()
    assert body["filters"]["donor_id"] == donor
    assert body["filters"]["hotspot_kind"] == "comment"
    assert "hotspot_severity" not in body["filters"]
    assert body["filters"]["min_overdue_hours"] == 24.0
    assert body["filters"]["top_limit"] == 5
    assert body["job_count"] == 2
    assert body["jobs_with_overdue"] == 1
    assert body["jobs_without_overdue"] == 1
    assert body["total_overdue_items"] == 1
    assert body["hotspot_count"] == 1
    assert body["top_donor_id"] == donor
    assert body["top_donor_overdue_count"] == 1
    assert body["donor_hotspot_counts"][donor] == 1
    assert body["job_hotspot_counts"]["portfolio-review-workflow-sla-hotspots-job-1"] == 1
    assert body["job_hotspot_counts"]["portfolio-review-workflow-sla-hotspots-job-2"] == 0
    assert len(body["top_overdue"]) == 1
    assert body["top_overdue"][0]["kind"] == "comment"
    assert body["top_overdue"][0]["job_id"] == "portfolio-review-workflow-sla-hotspots-job-1"
    assert body["top_overdue"][0]["donor_id"] == donor


def test_portfolio_review_workflow_sla_hotspots_export_supports_csv_json_and_gzip():
    donor = "portfolio_review_workflow_sla_hotspots_export_test_donor"
    runtime_state.JOB_STORE.set(
        "portfolio-review-workflow-sla-hotspots-export-job-1",
        {
            "status": "done",
            "hitl_enabled": True,
            "state": {
                "donor_id": donor,
                "critic_notes": {
                    "fatal_flaws": [
                        {
                            "finding_id": "prwh-exp-1",
                            "severity": "high",
                            "section": "toc",
                            "status": "open",
                            "updated_at": "2026-02-20T10:00:00+00:00",
                            "due_at": "2026-02-25T10:00:00+00:00",
                            "sla_hours": 24,
                        }
                    ]
                },
            },
            "review_comments": [
                {
                    "comment_id": "prwh-exp-comment-1",
                    "ts": "2026-02-27T10:05:00+00:00",
                    "section": "toc",
                    "status": "open",
                    "message": "Review needed.",
                    "linked_finding_id": "prwh-exp-1",
                    "due_at": "2026-02-25T11:00:00+00:00",
                    "sla_hours": 24,
                }
            ],
            "job_events": [
                {
                    "event_id": "prwh-exp-evt-1",
                    "ts": "2026-02-27T10:05:00+00:00",
                    "type": "review_comment_added",
                    "comment_id": "prwh-exp-comment-1",
                    "section": "toc",
                }
            ],
        },
    )

    csv_resp = client.get(
        "/portfolio/review-workflow/sla/hotspots/export",
        params={
            "donor_id": donor,
            "status": "done",
            "hitl_enabled": "true",
            "overdue_after_hours": 12,
            "hotspot_kind": "comment",
            "min_overdue_hours": 1,
            "top_limit": 3,
            "format": "csv",
        },
    )
    assert csv_resp.status_code == 200
    assert csv_resp.headers["content-type"].startswith("text/csv")
    csv_disposition = csv_resp.headers.get("content-disposition", "")
    assert f"grantflow_portfolio_review_workflow_sla_hotspots_{donor}_done_hitl_true.csv" in csv_disposition
    csv_text = csv_resp.text
    assert csv_text.startswith("field,value\n")
    assert f"filters.donor_id,{donor}" in csv_text
    assert "filters.hotspot_kind,comment" in csv_text
    assert "filters.top_limit,3" in csv_text

    json_resp = client.get(
        "/portfolio/review-workflow/sla/hotspots/export",
        params={
            "donor_id": donor,
            "overdue_after_hours": 12,
            "hotspot_kind": "comment",
            "format": "json",
        },
    )
    assert json_resp.status_code == 200
    assert json_resp.headers["content-type"].startswith("application/json")
    json_payload = json_resp.json()
    assert json_payload["filters"]["donor_id"] == donor
    assert json_payload["filters"]["hotspot_kind"] == "comment"
    assert json_payload["filters"]["hotspot_severity"] is None
    assert json_payload["hotspot_count"] == 1

    gzip_resp = client.get(
        "/portfolio/review-workflow/sla/hotspots/export",
        params={"donor_id": donor, "overdue_after_hours": 12, "format": "json", "gzip": "true"},
    )
    assert gzip_resp.status_code == 200
    assert gzip_resp.headers["content-type"].startswith("application/gzip")
    gzip_disposition = gzip_resp.headers.get("content-disposition", "")
    assert f"grantflow_portfolio_review_workflow_sla_hotspots_{donor}.json.gz" in gzip_disposition
    gzip_payload = json.loads(gzip.decompress(gzip_resp.content).decode("utf-8"))
    assert gzip_payload["filters"]["donor_id"] == donor
    assert gzip_payload["hotspot_count"] == 1
