import grantflow.api.routes.jobs as jobs_routes
from grantflow.api import runtime_state
from grantflow.core.config import config

from grantflow.tests.queue_dispatch_helpers import client


def test_generate_uses_inmemory_queue_dispatch_when_enabled(monkeypatch):
    captured: dict = {}

    def _submit_stub(fn, *args, **kwargs):
        captured["fn"] = fn
        captured["args"] = args
        captured["kwargs"] = kwargs
        return True

    monkeypatch.setattr(config.job_runner, "mode", "inmemory_queue")
    monkeypatch.setattr(runtime_state.JOB_RUNNER, "submit", _submit_stub)

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

    assert captured["fn"] == jobs_routes._run_pipeline_to_completion
    assert captured["args"][0] == job_id
    queued_state = captured["args"][1]
    assert queued_state["donor_id"] == "usaid"

    status_resp = client.get(f"/status/{job_id}")
    assert status_resp.status_code == 200
    assert status_resp.json()["status"] == "accepted"


def test_generate_returns_503_when_inmemory_queue_is_full(monkeypatch):
    monkeypatch.setattr(config.job_runner, "mode", "inmemory_queue")
    monkeypatch.setattr(runtime_state.JOB_RUNNER, "submit", lambda *args, **kwargs: False)

    response = client.post(
        "/generate",
        json={
            "donor_id": "usaid",
            "input_context": {"project": "Queue full", "country": "Kenya"},
            "llm_mode": False,
            "hitl_enabled": False,
        },
    )
    assert response.status_code == 503
    detail = response.json()["detail"]
    assert detail["code"] == "job_queue_full"
    assert detail["retryable"] is True


def test_generate_uses_redis_queue_dispatch_when_enabled(monkeypatch):
    captured: dict = {}

    def _submit_stub(fn, *args, **kwargs):
        captured["fn"] = fn
        captured["args"] = args
        captured["kwargs"] = kwargs
        return True

    monkeypatch.setattr(config.job_runner, "mode", "redis_queue")
    monkeypatch.setattr(runtime_state.JOB_RUNNER, "submit", _submit_stub)

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

    assert captured["fn"] == jobs_routes._run_pipeline_to_completion_by_job_id
    assert captured["args"][0] == job_id
    assert len(captured["args"]) == 1

    status_resp = client.get(f"/status/{job_id}")
    assert status_resp.status_code == 200
    assert status_resp.json()["status"] == "accepted"


def test_generate_hitl_uses_redis_queue_dispatch_by_job_id(monkeypatch):
    captured: dict = {}

    def _submit_stub(fn, *args, **kwargs):
        captured["fn"] = fn
        captured["args"] = args
        captured["kwargs"] = kwargs
        return True

    monkeypatch.setattr(config.job_runner, "mode", "redis_queue")
    monkeypatch.setattr(runtime_state.JOB_RUNNER, "submit", _submit_stub)

    response = client.post(
        "/generate",
        json={
            "donor_id": "usaid",
            "input_context": {"project": "Redis queue HITL dispatch", "country": "Kenya"},
            "llm_mode": False,
            "hitl_enabled": True,
        },
    )
    assert response.status_code == 200
    body = response.json()
    job_id = body["job_id"]

    assert captured["fn"] == jobs_routes._run_hitl_pipeline_by_job_id
    assert captured["args"] == (job_id, "start")
