# grantflow/tests/test_integration_quality_events_contract.py
"""
Contract tests for:
  GET /status/{job_id}/quality
  GET /status/{job_id}/events

Covers gaps not addressed by test_integration_quality_summary.py:
- 404 uses agent error format (code, retryable, next_action)
- Auth guard (quality:read and status:read scopes)
- Events endpoint shape and 404
- Events auth guard
"""

from fastapi.testclient import TestClient

from grantflow.api.app import app
from grantflow.tests.integration_helpers import wait_for_terminal_status

client = TestClient(app)

_GENERATE_BODY = {
    "donor_id": "usaid",
    "input_context": {"project": "Governance Reform", "country": "Georgia"},
    "llm_mode": False,
    "hitl_enabled": False,
}


def _run_job() -> str:
    res = client.post("/generate", json=_GENERATE_BODY)
    assert res.status_code == 200
    job_id = res.json()["job_id"]
    wait_for_terminal_status(client, job_id)
    return job_id


# ---------------------------------------------------------------------------
# /status/{job_id}/quality
# ---------------------------------------------------------------------------


def test_quality_404_is_agent_error_format():
    res = client.get("/status/nonexistent-quality-job-xyz/quality")
    assert res.status_code == 404
    detail = res.json()["detail"]
    assert detail["code"] == "job_not_found"
    assert detail["retryable"] is False
    assert "next_action" in detail


def test_quality_requires_api_key_when_configured(monkeypatch):
    job_id = _run_job()
    monkeypatch.setenv("GRANTFLOW_API_KEY", "test-secret")
    monkeypatch.setenv("GRANTFLOW_REQUIRE_AUTH_FOR_READS", "true")

    res = client.get(f"/status/{job_id}/quality")
    assert res.status_code == 401

    res = client.get(f"/status/{job_id}/quality", headers={"X-API-Key": "test-secret"})
    assert res.status_code == 200


def test_quality_top_level_keys_present():
    job_id = _run_job()
    res = client.get(f"/status/{job_id}/quality")
    assert res.status_code == 200
    body = res.json()
    for key in ("job_id", "status", "quality_score", "critic_score", "critic", "citations"):
        assert key in body, f"quality payload missing key: {key}"
    assert body["job_id"] == job_id


def test_quality_terminal_status_matches_status():
    job_id = _run_job()
    res = client.get(f"/status/{job_id}/quality")
    assert res.status_code == 200
    body = res.json()
    assert body.get("terminal_status") == body.get("status")


# ---------------------------------------------------------------------------
# /status/{job_id}/events
# ---------------------------------------------------------------------------


def test_events_shape_and_keys():
    job_id = _run_job()
    res = client.get(f"/status/{job_id}/events")
    assert res.status_code == 200
    body = res.json()
    assert body["job_id"] == job_id
    assert "status" in body
    assert isinstance(body["event_count"], int)
    assert isinstance(body["events"], list)
    assert body["event_count"] == len(body["events"])


def test_events_list_is_non_empty_after_completed_job():
    job_id = _run_job()
    res = client.get(f"/status/{job_id}/events")
    assert res.status_code == 200
    body = res.json()
    assert body["event_count"] > 0, "completed job must have at least one event"


def test_events_each_item_has_ts_and_type():
    job_id = _run_job()
    res = client.get(f"/status/{job_id}/events")
    assert res.status_code == 200
    for event in res.json()["events"]:
        assert "ts" in event, f"event missing ts: {event}"


def test_events_404_is_agent_error_format():
    res = client.get("/status/nonexistent-events-job-xyz/events")
    assert res.status_code == 404
    detail = res.json()["detail"]
    assert detail["code"] == "job_not_found"
    assert detail["retryable"] is False
    assert "next_action" in detail


def test_events_requires_api_key_when_configured(monkeypatch):
    job_id = _run_job()
    monkeypatch.setenv("GRANTFLOW_API_KEY", "test-secret")
    monkeypatch.setenv("GRANTFLOW_REQUIRE_AUTH_FOR_READS", "true")

    res = client.get(f"/status/{job_id}/events")
    assert res.status_code == 401

    res = client.get(f"/status/{job_id}/events", headers={"X-API-Key": "test-secret"})
    assert res.status_code == 200
