# grantflow/tests/test_integration_metrics_critic_contract.py
"""
Contract tests for:
  GET /status/{job_id}/metrics
  GET /status/{job_id}/critic

Covers gaps not addressed by existing tests:
- 404 uses agent error format (code, retryable, next_action)
- Auth guard
- Response shape: required top-level keys
"""

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": "Education Access", "country": "Tanzania"},
    "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}/metrics
# ---------------------------------------------------------------------------


def test_metrics_404_is_agent_error_format():
    res = client.get("/status/nonexistent-metrics-job-xyz/metrics")
    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_metrics_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}/metrics")
    assert res.status_code == 401

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


def test_metrics_top_level_keys_present():
    job_id = _run_job()
    res = client.get(f"/status/{job_id}/metrics")
    assert res.status_code == 200
    body = res.json()
    for key in ("job_id", "status", "terminal_status"):
        assert key in body, f"metrics payload missing key: {key}"
    assert body["job_id"] == job_id


def test_metrics_terminal_status_is_string():
    job_id = _run_job()
    res = client.get(f"/status/{job_id}/metrics")
    assert res.status_code == 200
    body = res.json()
    assert isinstance(body.get("terminal_status"), str)


# ---------------------------------------------------------------------------
# /status/{job_id}/critic
# ---------------------------------------------------------------------------


def test_critic_404_is_agent_error_format():
    res = client.get("/status/nonexistent-critic-job-xyz/critic")
    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_critic_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}/critic")
    assert res.status_code == 401

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


def test_critic_top_level_keys_present():
    job_id = _run_job()
    res = client.get(f"/status/{job_id}/critic")
    assert res.status_code == 200
    body = res.json()
    for key in ("job_id", "status", "fatal_flaw_count", "fatal_flaws", "rule_check_count", "rule_checks"):
        assert key in body, f"critic payload missing key: {key}"
    assert body["job_id"] == job_id


def test_critic_counts_match_list_lengths():
    job_id = _run_job()
    res = client.get(f"/status/{job_id}/critic")
    assert res.status_code == 200
    body = res.json()
    assert body["fatal_flaw_count"] == len(body["fatal_flaws"])
    assert body["rule_check_count"] == len(body["rule_checks"])
