from __future__ import annotations

from pathlib import Path

import pygit2
import pytest

from attractor.engine import Engine, EngineError, RunStatus
from attractor.worktree import InputCopy


@pytest.mark.asyncio
# [unit->REQ-LAUNCH-PATH-PREFLIGHT]
async def test_launch_path_returns_addressable_run_before_wait(
    seeded_repo: Path, human_gate_workflow: str
) -> None:
    wf = seeded_repo / "human.dot"
    wf.write_text(human_gate_workflow, encoding="utf-8")
    engine = Engine(seeded_repo)

    session = await engine.launch(wf)

    assert session.run_id
    assert not session.done()
    summary = engine.show(session.run_id)
    assert summary.run_id == session.run_id

    status = await session.wait()
    assert status == RunStatus.PAUSED


@pytest.mark.asyncio
# [unit->REQ-LAUNCH-PATH-PREFLIGHT]
async def test_launch_missing_workflow_file_rejects_without_run(
    seeded_repo: Path,
) -> None:
    engine = Engine(seeded_repo)

    with pytest.raises(EngineError, match="workflow file not found"):
        await engine.launch(seeded_repo / "missing.dot")

    assert _attractor_run_refs(seeded_repo) == []
    assert not (seeded_repo / ".attractor" / "worktrees").exists()


@pytest.mark.asyncio
# [unit->REQ-LAUNCH-PATH-PREFLIGHT]
async def test_launch_missing_input_rejects_before_worktree_creation(
    seeded_repo: Path, tool_only_workflow: str
) -> None:
    wf = seeded_repo / "tool.dot"
    wf.write_text(tool_only_workflow, encoding="utf-8")
    engine = Engine(seeded_repo)

    with pytest.raises(EngineError, match=r"input source .* does not exist"):
        await engine.launch(
            wf,
            inputs=[InputCopy(name="goal.md", source=seeded_repo / "missing.md")],
        )

    assert _attractor_run_refs(seeded_repo) == []
    assert not (seeded_repo / ".attractor" / "worktrees").exists()


@pytest.mark.asyncio
# [unit->REQ-LAUNCH-PATH-PREFLIGHT]
async def test_launch_bad_base_ref_rejects_without_run(
    seeded_repo: Path, tool_only_workflow: str
) -> None:
    wf = seeded_repo / "tool.dot"
    wf.write_text(tool_only_workflow, encoding="utf-8")
    engine = Engine(seeded_repo)

    with pytest.raises(EngineError, match="base ref 'does-not-exist'"):
        await engine.launch(wf, base_ref="does-not-exist")

    assert _attractor_run_refs(seeded_repo) == []
    assert not (seeded_repo / ".attractor" / "worktrees").exists()


def _attractor_run_refs(repo_root: Path) -> list[str]:
    repo = pygit2.Repository(str(repo_root))
    return sorted(
        ref for ref in repo.references if ref.startswith("refs/heads/attractor/run/")
    )
