"""Shared fixtures for CLI tests.

CLI tests need a real git repo and the ability to invoke `attractor`
as a subprocess. Tests cd into the seeded repo and shell out to
`uv run attractor` (or use `CliRunner` for in-process tests). The
`seeded_repo` fixture delegates to `attractor.testing.create_test_repo`.
"""

from __future__ import annotations

import shutil
from collections.abc import Sequence
from pathlib import Path

import pytest

from attractor.execution import local as _local_exec
from attractor.testing import create_test_repo


def _pick_test_shell() -> tuple[str, Sequence[str]] | None:
    """Return a usable shell. Mirrors test_engine/conftest.py."""
    pwsh = shutil.which("pwsh")
    if pwsh is not None:
        return (pwsh, ("-NoProfile", "-Command"))
    sh = shutil.which("sh")
    if sh is not None:
        return (sh, ("-c",))
    return None


@pytest.fixture(autouse=True)
def _patch_shell(  # pyright: ignore[reportUnusedFunction]
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    """Autouse: patch the shell resolver for in-process tests.

    The subprocess-based §16 DoD test runs in a child process, so this
    fixture has no effect there; it only matters for in-process CliRunner
    tests below. The DoD scenario is designed to use only `echo`-style
    commands that work uniformly across pwsh and sh.
    """
    picked = _pick_test_shell()
    if picked is None:
        pytest.skip("no usable shell on PATH (need pwsh or sh)")

    def _patched() -> tuple[str, Sequence[str]]:
        return picked

    monkeypatch.setattr(_local_exec, "_resolve_shell", _patched)


@pytest.fixture()
def seeded_repo(tmp_path: Path) -> Path:
    """A repo at `tmp_path / repo/` with one commit on `main`."""
    return create_test_repo(tmp_path / "repo")
