"""
test_bot_authored_pr.py — PR author bot 검증 회귀 테스트.

--bot-author 플래그 지정 시 PR author가 사람이면 즉시 차단(fail-closed) 검증.
"""
from __future__ import annotations

import json
import sys
from pathlib import Path

import pytest

# worktree 루트를 sys.path에 추가
_WORKTREE_ROOT = str(Path(__file__).resolve().parents[2])
if _WORKTREE_ROOT not in sys.path:
    sys.path.insert(0, _WORKTREE_ROOT)

_SCRIPTS_DIR = str(Path(__file__).resolve().parents[2] / "scripts")
if _SCRIPTS_DIR not in sys.path:
    sys.path.insert(0, _SCRIPTS_DIR)


def _make_state(tmp_path: Path, task_id: str) -> dict:
    """테스트용 task state json 생성."""
    import hashlib, json as _json

    state_dir = tmp_path / ".tasks" / "state"
    state_dir.mkdir(parents=True, exist_ok=True)

    state: dict = {
        "task_id": task_id,
        "current_state": "COMMITTED",
        "transitions": [],
        "evidence": {
            "git_diff_sha": None,
            "changed_paths": [],
            "branch": None,
            "pr_number": None,
            "pr_state": None,
            "ci_checks": {},
            "guard_sh_result": None,
            "gemini_evidence": None,
            "qc_report": None,
        },
    }

    def _canonical(s: dict) -> str:
        payload = {k: v for k, v in s.items() if k != "_checksum"}
        return _json.dumps(payload, ensure_ascii=False, sort_keys=True, separators=(",", ":"))

    checksum = hashlib.sha256(_canonical(state).encode()).hexdigest()
    state["_checksum"] = checksum

    state_path = state_dir / f"{task_id}.json"
    state_path.write_text(_json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8")
    return state


def test_pr_open_bot_author_flag_rejects_human_pr(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
    """--bot-author 지정 + human PR author → 종료코드 != 0, ESCALATED / FAIL 기록."""
    import argparse

    task_id = "task-2481"
    monkeypatch.setenv("WORKSPACE_ROOT", str(tmp_path))
    monkeypatch.setenv("TASKCTL_TEST_MODE", "1")
    monkeypatch.setenv("TASKCTL_PR_AUTHOR_OVERRIDE", "human-user")

    _make_state(tmp_path, task_id)

    # taskctl 모듈을 fresh-import (WORKSPACE_ROOT 환경변수 반영)
    # tests/taskctl 패키지와 충돌을 피해 importlib로 직접 파일 로드
    import importlib.util

    taskctl_path = Path(_WORKTREE_ROOT) / "scripts" / "taskctl.py"
    spec = importlib.util.spec_from_file_location("_taskctl_scripts", str(taskctl_path))
    tc = importlib.util.module_from_spec(spec)  # type: ignore[arg-type]
    spec.loader.exec_module(tc)  # type: ignore[union-attr]

    # WORKSPACE 경로를 tmp_path로 재설정
    monkeypatch.setattr(tc, "WORKSPACE", tmp_path)
    monkeypatch.setattr(tc, "STATE_DIR", tmp_path / ".tasks" / "state")
    monkeypatch.setattr(tc, "EVIDENCE_DIR", tmp_path / ".tasks" / "evidence")

    args = argparse.Namespace(
        task_id=task_id,
        pr=999,
        auto=False,
        bot_author=True,
    )

    with pytest.raises(SystemExit) as exc_info:
        tc.cmd_pr_open(args)

    # 종료코드 != 0 검증
    assert exc_info.value.code != 0, f"expected non-zero exit, got {exc_info.value.code}"

    # state 파일에서 ESCALATED 기록 확인
    state_file = tmp_path / ".tasks" / "state" / f"{task_id}.json"
    if state_file.exists():
        state_data = json.loads(state_file.read_text())
        # ESCALATED 상태이거나 transitions에 ESCALATED 기록
        transitions = state_data.get("transitions", [])
        escalated = any(t.get("to") == "ESCALATED" for t in transitions)
        assert escalated, f"ESCALATED transition not found in state: {transitions}"

    # evidence 파일에서 bot_author_check=FAIL 또는 ESCALATED 흔적 확인
    evidence_dir = tmp_path / ".tasks" / "evidence" / task_id
    if evidence_dir.exists():
        ev_files = list(evidence_dir.glob("*.json"))
        if ev_files:
            ev_data = json.loads(ev_files[-1].read_text())
            # FAIL 또는 ESCALATED 흔적
            fail_found = (
                ev_data.get("bot_author_check") == "FAIL"
                or ev_data.get("result") == "FAIL"
                or "ESCALATED" in str(ev_data)
                or "non-bot" in str(ev_data)
                or "FAIL" in str(ev_data)
            )
            assert fail_found, f"FAIL evidence not found: {ev_data}"
