"""main 브랜치 충돌 가능성을 사전 점검하는 4-step preflight 헬퍼."""

from __future__ import annotations

import subprocess
from typing import Optional

VALID_DECISIONS: tuple = ("SAFE", "LIKELY_CONFLICT", "ABORT_FETCH_RETRY")

_TIMEOUT_SEC: int = 30


def _run_git(args: list[str], cwd: str) -> subprocess.CompletedProcess:
    """지정한 worktree에서 git 명령을 실행한다."""
    return subprocess.run(
        args,
        cwd=cwd,
        capture_output=True,
        text=True,
        timeout=_TIMEOUT_SEC,
    )


def check_conflict_likelihood(
    worktree_path: str,
    expected_files: list[str],
) -> tuple[str, dict]:
    """worktree와 origin/main 사이의 충돌 가능성을 4-step으로 점검한다."""
    evidence: dict = {
        "fetch_ok": False,
        "remote_sha": None,
        "diff_files": [],
        "conflict_files": [],
        "decision_reason": "",
    }

    # step1: git fetch origin main --prune
    try:
        fetch_proc = _run_git(
            ["git", "fetch", "origin", "main", "--prune"],
            cwd=worktree_path,
        )
    except (subprocess.TimeoutExpired, FileNotFoundError, OSError) as exc:
        evidence["decision_reason"] = f"step1 fetch raised: {exc!r}"
        return "ABORT_FETCH_RETRY", evidence

    if fetch_proc.returncode != 0:
        evidence["decision_reason"] = (
            f"step1 fetch failed rc={fetch_proc.returncode} "
            f"stderr={fetch_proc.stderr.strip()[:200]}"
        )
        return "ABORT_FETCH_RETRY", evidence

    evidence["fetch_ok"] = True

    # step2: git ls-remote origin main (HEAD SHA)
    remote_sha: Optional[str] = None
    try:
        ls_remote_proc = _run_git(
            ["git", "ls-remote", "origin", "main"],
            cwd=worktree_path,
        )
        if ls_remote_proc.returncode == 0 and ls_remote_proc.stdout.strip():
            remote_sha = ls_remote_proc.stdout.split()[0]
            evidence["remote_sha"] = remote_sha
        else:
            evidence["decision_reason"] = (
                f"step2 ls-remote failed rc={ls_remote_proc.returncode}"
            )
    except (subprocess.TimeoutExpired, FileNotFoundError, OSError) as exc:
        evidence["decision_reason"] = f"step2 ls-remote raised: {exc!r}"

    # step3: git rev-parse origin/main (local ref)
    try:
        rev_parse_proc = _run_git(
            ["git", "rev-parse", "origin/main"],
            cwd=worktree_path,
        )
        if rev_parse_proc.returncode != 0:
            evidence["decision_reason"] = (
                evidence["decision_reason"]
                or f"step3 rev-parse failed rc={rev_parse_proc.returncode}"
            )
    except (subprocess.TimeoutExpired, FileNotFoundError, OSError) as exc:
        evidence["decision_reason"] = (
            evidence["decision_reason"] or f"step3 rev-parse raised: {exc!r}"
        )

    # step4: git diff origin/main --name-only
    diff_files: list[str] = []
    try:
        diff_proc = _run_git(
            ["git", "diff", "origin/main", "--name-only"],
            cwd=worktree_path,
        )
        if diff_proc.returncode == 0:
            diff_files = [
                line.strip()
                for line in diff_proc.stdout.splitlines()
                if line.strip()
            ]
        else:
            evidence["decision_reason"] = (
                evidence["decision_reason"]
                or f"step4 diff failed rc={diff_proc.returncode}"
            )
    except (subprocess.TimeoutExpired, FileNotFoundError, OSError) as exc:
        evidence["decision_reason"] = (
            evidence["decision_reason"] or f"step4 diff raised: {exc!r}"
        )

    evidence["diff_files"] = diff_files

    expected_set = set(expected_files)
    conflict_files = sorted(set(diff_files) & expected_set)
    evidence["conflict_files"] = conflict_files

    if conflict_files:
        evidence["decision_reason"] = (
            f"intersection with expected_files: {conflict_files}"
        )
        return "LIKELY_CONFLICT", evidence

    if not evidence["decision_reason"]:
        evidence["decision_reason"] = (
            "no intersection between diff_files and expected_files"
        )
    return "SAFE", evidence
