"""Shared test helpers: in-process fake orchestrator and task factory."""
from __future__ import annotations

import tempfile
from pathlib import Path

from dual_agent.adapters.fake import FakeAgentAdapter
from dual_agent.domain import TaskRecord, TaskSpec, TaskState
from dual_agent.persistence import TaskStore
from dual_agent.services import Orchestrator

FAKE_PLANNER_RESPONSES = {
    "PLAN": (
        '{"schema_version":1,"goal":"fake plan","acceptance_criteria":["tests pass"],'
        '"steps":[{"schema_version":1,"id":"P1","action":"noop","verification":"done"}]}'
    ),
    "REVIEW": '{"schema_version":1,"verdict":"PASS","issues":[],"summary":"ok"}',
    "FINAL_VERIFY": '{"schema_version":1,"verdict":"PASS","issues":[],"summary":"ok"}',
}

FAKE_IMPLEMENTER_RESPONSES = {
    "PLAN_REVIEW": '{"schema_version":1,"verdict":"PASS","issues":[],"summary":"ok"}',
    "IMPLEMENT": '{"schema_version":1,"files_changed":[],"tests_run":[],"notes":"fake"}',
    "FIX": '{"schema_version":1,"resolved":[],"not_resolved":[],"extra_changes":[],"tests_run":[]}',
}


class _FakeWorkspace:
    def create(self, task_id: str, repo_path: Path) -> tuple[Path, str]:
        import subprocess
        head = subprocess.check_output(["git", "-C", str(repo_path), "rev-parse", "HEAD"], text=True).strip()
        return repo_path, head


class _FakeTestRunner:
    def __call__(self, task: TaskRecord, worktree: Path):
        return True


def fake_orchestrator(tmp_dir: str | None = None) -> Orchestrator:
    """Return an Orchestrator wired with fake adapters for testing."""
    root = Path(tmp_dir) if tmp_dir else Path(tempfile.mkdtemp())
    store = TaskStore(root)
    planner = FakeAgentAdapter(FAKE_PLANNER_RESPONSES)
    implementer = FakeAgentAdapter(FAKE_IMPLEMENTER_RESPONSES)
    return Orchestrator(
        store=store,
        planner=planner,
        implementer=implementer,
        workspace=_FakeWorkspace(),
        test_runner=_FakeTestRunner(),
        lock_timeout_s=0.0,
    )


def task_in_state(orc: Orchestrator, state: str) -> TaskRecord:
    """Create a task and drive it to the requested state (INIT is immediate)."""
    repo = Path(tempfile.mkdtemp())
    # git init so baseline commit works
    import subprocess
    subprocess.run(["git", "-C", str(repo), "init", "-q"], check=True)
    subprocess.run(["git", "-C", str(repo), "-c", "user.name=Test", "-c", "user.email=test@example.invalid", "commit", "--allow-empty", "-m", "init", "-q"], check=True)

    task = orc.create_task(TaskSpec(repo_path=repo, goal="test task"))
    if state == "INIT":
        return task

    # Drive until we hit the desired state or terminal
    from dual_agent.domain import is_terminal
    for _ in range(20):
        if task.state.value == state or is_terminal(task.state):
            break
        task = orc.advance(task.task_id)
    return orc.get_task(task.task_id)
