"""4-step preflight 계약 회귀 테스트 (evidence 키, 상수, cwd 전달)."""

from __future__ import annotations

import subprocess
import sys
from pathlib import Path

import pytest

# workspace root → sys.path (기존 regression 테스트 패턴 준수)
_WORKSPACE = Path(__file__).resolve().parent.parent.parent.parent
if str(_WORKSPACE) in sys.path:
    sys.path.remove(str(_WORKSPACE))
sys.path.insert(0, str(_WORKSPACE))

from utils import main_conflict_preflight as mcp  # type: ignore[reportMissingImports] # noqa: E402


def _make_completed(
    args: list[str],
    returncode: int = 0,
    stdout: str = "",
    stderr: str = "",
) -> subprocess.CompletedProcess:
    return subprocess.CompletedProcess(
        args=args,
        returncode=returncode,
        stdout=stdout,
        stderr=stderr,
    )


def _build_safe_run():
    """모든 step이 정상 성공하는 fake subprocess.run."""

    def fake_run(args, **_kwargs):
        # _kwargs: cwd / capture_output / text / timeout (mock에서 검증 안 함)
        sub = args[1] if len(args) > 1 else ""
        if sub == "fetch":
            return _make_completed(args, returncode=0)
        if sub == "ls-remote":
            return _make_completed(
                args, returncode=0, stdout="cafef00d\trefs/heads/main\n"
            )
        if sub == "rev-parse":
            return _make_completed(args, returncode=0, stdout="cafef00d\n")
        if sub == "diff":
            return _make_completed(args, returncode=0, stdout="x\ny\n")
        return _make_completed(args, returncode=0)

    return fake_run


def test_evidence_dict_has_required_keys(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    monkeypatch.setattr(mcp.subprocess, "run", _build_safe_run())

    decision, evidence = mcp.check_conflict_likelihood(
        "/tmp/fake-worktree", ["unrelated"]
    )

    assert decision == "SAFE"
    required_keys = {
        "fetch_ok",
        "remote_sha",
        "diff_files",
        "conflict_files",
        "decision_reason",
    }
    assert required_keys.issubset(evidence.keys())
    assert len(required_keys & evidence.keys()) == 5


def test_valid_decisions_constant() -> None:
    assert mcp.VALID_DECISIONS == (
        "SAFE",
        "LIKELY_CONFLICT",
        "ABORT_FETCH_RETRY",
    )


def test_subprocess_called_with_cwd(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    captured_cwds: list = []

    def fake_run(args, cwd=None, **_kwargs):
        # _kwargs: capture_output / text / timeout (mock에서 사용 안 함)
        captured_cwds.append(cwd)
        sub = args[1] if len(args) > 1 else ""
        if sub == "ls-remote":
            return _make_completed(
                args, returncode=0, stdout="abc\trefs/heads/main\n"
            )
        if sub == "diff":
            return _make_completed(args, returncode=0, stdout="")
        return _make_completed(args, returncode=0, stdout="")

    monkeypatch.setattr(mcp.subprocess, "run", fake_run)

    worktree = "/tmp/specific-worktree-path"
    decision, evidence = mcp.check_conflict_likelihood(worktree, [])

    assert decision == "SAFE"
    assert "fetch_ok" in evidence  # evidence shape sanity
    assert captured_cwds, "subprocess.run was never called"
    assert all(cwd == worktree for cwd in captured_cwds)
    # 4 steps must have been invoked
    assert len(captured_cwds) == 4
