import asyncio

import pytest

from app.modules.agent.engine.orchestrator.models import OutputContract, RoutingMeta, Scenario, TaskConstraints, TaskSpec
from app.modules.agent.engine.orchestrator.service import OrchestratorService


@pytest.mark.parametrize(
    "scenario,expect_changeset",
    [
        (Scenario.EXPLAIN_PART, False),
        (Scenario.ANALYTICS_REVIEW, False),
        (Scenario.DOCS_FROM_ANALYTICS, True),
        (Scenario.TARGETED_EDIT, True),
        (Scenario.GHERKIN_MODEL, True),
    ],
)
def test_eval_suite_scenarios_run(scenario: Scenario, expect_changeset: bool) -> None:
    service = OrchestratorService()

    task = TaskSpec(
        task_id=f"task-{scenario.value}",
        dialog_session_id="dialog-1",
        rag_session_id="rag-1",
        mode="auto",
        user_message="Please process this scenario using project docs and requirements.",
        scenario=scenario,
        routing=RoutingMeta(domain_id="project", process_id="qa", confidence=0.95, reason="eval"),
        constraints=TaskConstraints(
            allow_writes=scenario in {Scenario.DOCS_FROM_ANALYTICS, Scenario.TARGETED_EDIT, Scenario.GHERKIN_MODEL},
            max_steps=20,
            max_retries_per_step=2,
            step_timeout_sec=90,
        ),
        output_contract=OutputContract(result_type="answer"),
        attachments=[{"type": "http_url", "value": "https://example.com/doc"}],
        metadata={
            "rag_context": "Requirements context is available.",
            "confluence_context": "",
            "files_map": {"docs/api/increment.md": {"content": "old", "content_hash": "h1"}},
        },
    )

    result = asyncio.run(
        service.run(
            task=task,
            graph_resolver=lambda _domain, _process: object(),
            graph_invoker=lambda _graph, _state, _dialog: {"answer": "fallback", "changeset": []},
        )
    )

    assert result.meta["plan"]["status"] in {"completed", "partial"}
    assert bool(result.changeset) is expect_changeset
    if not expect_changeset:
        assert result.answer
