from fastapi.testclient import TestClient

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

client = TestClient(app)


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

    versions_resp = client.get(f"/status/{job_id}/versions", params={"section": "toc"})
    assert versions_resp.status_code == 200
    versions = versions_resp.json()["versions"]
    assert versions
    toc_version_id = versions[-1]["version_id"]

    create_resp = client.post(
        f"/status/{job_id}/comments",
        json={
            "section": "toc",
            "message": "Please tighten assumptions and clarify beneficiary targeting.",
            "author": "reviewer-1",
            "version_id": toc_version_id,
        },
    )
    assert create_resp.status_code == 200
    created = create_resp.json()
    assert created["section"] == "toc"
    assert created["status"] == "open"
    assert created["version_id"] == toc_version_id
    assert created["author"] == "reviewer-1"
    assert isinstance(created.get("due_at"), str) and created["due_at"]
    assert int(created.get("sla_hours") or 0) >= 1

    comments_resp = client.get(f"/status/{job_id}/comments")
    assert comments_resp.status_code == 200
    comments_body = comments_resp.json()
    assert comments_body["job_id"] == job_id
    assert comments_body["comment_count"] >= 1
    assert any(c["comment_id"] == created["comment_id"] for c in comments_body["comments"])

    ack_resp = client.post(f"/status/{job_id}/comments/{created['comment_id']}/ack")
    assert ack_resp.status_code == 200
    acknowledged = ack_resp.json()
    assert acknowledged["comment_id"] == created["comment_id"]
    assert acknowledged["status"] == "acknowledged"

    resolve_resp = client.post(f"/status/{job_id}/comments/{created['comment_id']}/resolve")
    assert resolve_resp.status_code == 200
    resolved = resolve_resp.json()
    assert resolved["comment_id"] == created["comment_id"]
    assert resolved["status"] == "resolved"
    assert isinstance(resolved.get("due_at"), str) and resolved["due_at"]

    resolved_filter_resp = client.get(f"/status/{job_id}/comments", params={"status": "resolved"})
    assert resolved_filter_resp.status_code == 200
    resolved_filter_body = resolved_filter_resp.json()
    assert any(c["comment_id"] == created["comment_id"] for c in resolved_filter_body["comments"])

    reopen_resp = client.post(f"/status/{job_id}/comments/{created['comment_id']}/reopen")
    assert reopen_resp.status_code == 200
    reopened = reopen_resp.json()
    assert reopened["comment_id"] == created["comment_id"]
    assert reopened["status"] == "open"
    assert isinstance(reopened.get("due_at"), str) and reopened["due_at"]
    assert reopened["due_at"] != resolved["due_at"]

    filtered_resp = client.get(
        f"/status/{job_id}/comments",
        params={"section": "toc", "status": "open", "version_id": toc_version_id},
    )
    assert filtered_resp.status_code == 200
    filtered_body = filtered_resp.json()
    assert filtered_body["comment_count"] >= 1
    assert all(c["section"] == "toc" for c in filtered_body["comments"])
    assert all(c["status"] == "open" for c in filtered_body["comments"])
    assert all((c.get("version_id") or "") == toc_version_id for c in filtered_body["comments"])

    status_resp = client.get(f"/status/{job_id}")
    assert status_resp.status_code == 200
    assert "review_comments" not in status_resp.json()


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

    bad_section = client.post(
        f"/status/{job_id}/comments",
        json={"section": "budget", "message": "Budget narrative mismatch"},
    )
    assert bad_section.status_code == 400

    bad_version = client.post(
        f"/status/{job_id}/comments",
        json={"section": "toc", "message": "Version mismatch", "version_id": "missing-version"},
    )
    assert bad_version.status_code == 400
