# grantflow/tests/test_integration_generation_mel.py

from fastapi.testclient import TestClient

import grantflow.api.routes.jobs as jobs_routes
from grantflow.api.app import app
from grantflow.core.config import config
from grantflow.memory_bank.vector_store import vector_store
from grantflow.tests.integration_helpers import wait_for_terminal_status

client = TestClient(app)


def test_strict_mel_grounding_policy_blocks_job_finalization(monkeypatch):
    monkeypatch.setattr(config.graph, "mel_grounding_policy_mode", "strict")
    monkeypatch.setattr(config.graph, "mel_grounding_min_mel_citations", 2)
    monkeypatch.setattr(config.graph, "mel_grounding_min_claim_support_rate", 0.75)
    monkeypatch.setattr(config.graph, "grounding_gate_mode", "warn")
    monkeypatch.setattr(
        jobs_routes,
        "_build_generate_preflight",
        lambda donor_id, strategy, client_metadata, **kwargs: {
            "donor_id": donor_id,
            "risk_level": "low",
            "grounding_risk_level": "low",
            "go_ahead": True,
            "warning_count": 0,
            "warnings": [],
            "retrieval_namespace": "usaid_ads201",
            "namespace_empty": False,
            "grounding_policy": {
                "mode": "warn",
                "risk_level": "low",
                "blocking": False,
                "go_ahead": True,
                "summary": "readiness_signals_ok",
                "reasons": ["sufficient_readiness_signals"],
            },
        },
    )
    monkeypatch.setattr(
        vector_store,
        "query",
        lambda namespace, query_texts, n_results=5, where=None, top_k=None: {
            "documents": [[]],
            "metadatas": [[]],
            "ids": [[]],
            "distances": [[]],
        },
    )

    response = client.post(
        "/generate",
        json={
            "donor_id": "usaid",
            "input_context": {"project": "Gov services modernization", "country": "Kenya"},
            "llm_mode": False,
            "hitl_enabled": False,
        },
    )
    assert response.status_code == 200
    job_id = response.json()["job_id"]

    terminal = wait_for_terminal_status(client, job_id)
    assert terminal["status"] == "error"
    assert "MEL grounding policy (strict) blocked finalization" in str(terminal.get("error") or "")
    state = terminal.get("state") or {}
    mel_policy = state.get("mel_grounding_policy") or {}
    assert mel_policy.get("mode") == "strict"
    assert mel_policy.get("blocking") is True
    assert mel_policy.get("passed") is False
    assert "mel_claim_support_rate_below_min" in (mel_policy.get("reasons") or [])


def test_strict_mel_grounding_policy_blocks_after_hitl_resume(monkeypatch):
    monkeypatch.setattr(config.graph, "mel_grounding_policy_mode", "strict")
    monkeypatch.setattr(config.graph, "mel_grounding_min_mel_citations", 2)
    monkeypatch.setattr(config.graph, "mel_grounding_min_claim_support_rate", 0.75)
    monkeypatch.setattr(config.graph, "grounding_gate_mode", "warn")
    monkeypatch.setattr(
        jobs_routes,
        "_build_generate_preflight",
        lambda donor_id, strategy, client_metadata, **kwargs: {
            "donor_id": donor_id,
            "risk_level": "low",
            "grounding_risk_level": "low",
            "go_ahead": True,
            "warning_count": 0,
            "warnings": [],
            "retrieval_namespace": "usaid_ads201",
            "namespace_empty": False,
            "grounding_policy": {
                "mode": "warn",
                "risk_level": "low",
                "blocking": False,
                "go_ahead": True,
                "summary": "readiness_signals_ok",
                "reasons": ["sufficient_readiness_signals"],
            },
        },
    )
    monkeypatch.setattr(
        vector_store,
        "query",
        lambda namespace, query_texts, n_results=5, where=None, top_k=None: {
            "documents": [[]],
            "metadatas": [[]],
            "ids": [[]],
            "distances": [[]],
        },
    )

    response = client.post(
        "/generate",
        json={
            "donor_id": "usaid",
            "input_context": {"project": "Gov services modernization", "country": "Kenya"},
            "llm_mode": False,
            "hitl_enabled": True,
        },
    )
    assert response.status_code == 200
    job_id = response.json()["job_id"]

    terminal = None
    resume_targets = []
    # GrantFlow may re-enter HITL checkpoints across revision iterations.
    # Keep approving and resuming until the job reaches a terminal non-HITL status.
    for _ in range(10):
        status = wait_for_terminal_status(client, job_id, timeout_s=5.0)
        if status["status"] != "pending_hitl":
            terminal = status
            break
        cp_id = status["checkpoint_id"]
        approve = client.post("/hitl/approve", json={"checkpoint_id": cp_id, "approved": True, "feedback": "ok"})
        assert approve.status_code == 200
        resume = client.post(f"/resume/{job_id}", json={})
        assert resume.status_code == 200
        resume_from = str(resume.json().get("resuming_from") or "")
        resume_targets.append(resume_from)
    assert terminal is not None, "Timed out waiting for job finalization with repeated HITL resumes"
    assert "mel" in resume_targets
    assert "critic" in resume_targets
    assert terminal["status"] == "error"
    assert "MEL grounding policy (strict) blocked finalization" in str(terminal.get("error") or "")
    state = terminal.get("state") or {}
    mel_policy = state.get("mel_grounding_policy") or {}
    assert mel_policy.get("blocking") is True
