"""tests/handoff/test_create.py
create_handoff.py 생성 테스트:
- test_create_basic: 필수 필드 확인
- test_create_4000_split: 4000자 초과 시 pending_work_path + 외부 파일 생성
- test_create_invalid_reason: 잘못된 reason → exit 1
"""
from __future__ import annotations

import json
import os
import subprocess
from pathlib import Path

SCRIPT = Path("/home/jay/workspace/.worktrees/task-2454-dev4/scripts/create_handoff.py")
WORKTREE = Path("/home/jay/workspace/.worktrees/task-2454-dev4")

REQUIRED_FIELDS = [
    "task_id",
    "schema_version",
    "previous_bot",
    "current_branch",
    "base_sha",
    "head_sha",
    "changed_paths",
    "allowed_paths",
    "forbidden_paths",
    "test_results",
    "handoff_reason",
    "created_at",
]

# 스키마 패턴: ^task-\d+(\.\d+)?$ — 숫자만 허용
# 테스트용 task-id는 반드시 이 패턴에 맞아야 함
TEST_TASK_BASIC = "task-9001"
TEST_TASK_LARGE = "task-9002"
TEST_TASK_REASONS = {
    "interrupt": "task-9003",
    "complete": "task-9004",
    "takeover_request": "task-9005",
}


def _run_handoff(args: list[str], workspace_root: Path | None = None) -> subprocess.CompletedProcess:
    """create_handoff.py 실행 헬퍼."""
    env = dict(os.environ)
    if workspace_root:
        env["WORKSPACE_ROOT"] = str(workspace_root)
    else:
        env["WORKSPACE_ROOT"] = str(WORKTREE)

    return subprocess.run(
        ["python3", str(SCRIPT)] + args,
        cwd=str(WORKTREE),
        capture_output=True,
        text=True,
        timeout=30,
        env=env,
    )


# ---------------------------------------------------------------------------
# test_create_basic
# ---------------------------------------------------------------------------

def test_create_basic():
    """기본 실행: 필수 필드가 모두 존재하는 JSON 생성 확인."""
    task_id = TEST_TASK_BASIC
    handoff_path = WORKTREE / "memory" / "handoffs" / f"{task_id}.json"

    # 기존 파일 정리
    if handoff_path.exists():
        handoff_path.unlink()

    result = _run_handoff([
        "--task", task_id,
        "--reason", "interrupt",
        "--pending", "테스트 잔여 작업",
        "--bot", "dev4",
    ])

    try:
        assert result.returncode == 0, (
            f"create_handoff.py 실패\nstdout: {result.stdout}\nstderr: {result.stderr}"
        )

        assert handoff_path.exists(), f"handoff JSON 미생성: {handoff_path}"

        data = json.loads(handoff_path.read_text(encoding="utf-8"))

        # 필수 필드 확인
        for field in REQUIRED_FIELDS:
            assert field in data, f"필수 필드 누락: {field}"

        # 값 검증
        assert data["task_id"] == task_id
        assert data["handoff_reason"] == "interrupt"
        assert data["previous_bot"] == "dev4"
        assert data["schema_version"] == "1.0"
        assert isinstance(data["changed_paths"], list)
        assert isinstance(data["test_results"], dict)

        # pending_work 인라인 확인
        assert "pending_work" in data
        assert data["pending_work"] == "테스트 잔여 작업"
        assert "pending_work_path" not in data

    finally:
        # 정리
        if handoff_path.exists():
            handoff_path.unlink()


# ---------------------------------------------------------------------------
# test_create_4000_split
# ---------------------------------------------------------------------------

def test_create_4000_split():
    """5000자 pending 텍스트 → pending_work_path + 외부 파일 생성 확인."""
    task_id = TEST_TASK_LARGE
    handoff_path = WORKTREE / "memory" / "handoffs" / f"{task_id}.json"
    txt_path = WORKTREE / "memory" / "handoffs" / f"{task_id}-pending.txt"

    # 기존 파일 정리
    for p in [handoff_path, txt_path]:
        if p.exists():
            p.unlink()

    long_pending = "x" * 5000  # 5000자 > 4000자 한도

    result = _run_handoff([
        "--task", task_id,
        "--reason", "interrupt",
        "--pending", long_pending,
        "--bot", "dev4",
    ])

    try:
        assert result.returncode == 0, (
            f"create_handoff.py 실패\nstdout: {result.stdout}\nstderr: {result.stderr}"
        )

        assert handoff_path.exists(), f"handoff JSON 미생성: {handoff_path}"
        data = json.loads(handoff_path.read_text(encoding="utf-8"))

        # pending_work_path 존재, pending_work 미존재
        assert "pending_work_path" in data, (
            f"pending_work_path 필드 없음 (4000자 초과인데 인라인 저장됨?)\ndata keys: {list(data.keys())}"
        )
        assert "pending_work" not in data, (
            f"pending_work 필드가 남아있음 (4000자 초과인데 인라인 저장됨?)"
        )

        # 외부 파일 생성 확인
        external_path = Path(data["pending_work_path"])
        # WORKSPACE_ROOT 기준 상대 경로일 수 있으므로 절대 경로로 변환
        if not external_path.is_absolute():
            external_path = WORKTREE / external_path
        assert external_path.exists(), f"외부 파일 미생성: {external_path}"

        # 외부 파일 내용 확인
        content = external_path.read_text(encoding="utf-8")
        assert content == long_pending, (
            f"외부 파일 내용 불일치 (길이: {len(content)} vs 기대: {len(long_pending)})"
        )

    finally:
        # 정리
        for p in [handoff_path, txt_path]:
            if p.exists():
                p.unlink()
        # pending_work_path가 가리키는 파일도 정리
        try:
            data = json.loads(handoff_path.read_text(encoding="utf-8")) if handoff_path.exists() else {}
            if "pending_work_path" in data:
                ext = Path(data["pending_work_path"])
                if not ext.is_absolute():
                    ext = WORKTREE / ext
                if ext.exists():
                    ext.unlink()
        except Exception:
            pass


# ---------------------------------------------------------------------------
# test_create_invalid_reason
# ---------------------------------------------------------------------------

def test_create_invalid_reason():
    """잘못된 reason 값으로 실행 시 exit 1 확인."""
    task_id = "task-9006"

    result = _run_handoff([
        "--task", task_id,
        "--reason", "invalid_reason_xyz",
        "--pending", "테스트",
        "--bot", "dev4",
    ])

    assert result.returncode != 0, (
        f"잘못된 reason에서 exit 0 (비정상)\nstdout: {result.stdout}\nstderr: {result.stderr}"
    )
    # argparse 에러 또는 스키마 검증 실패
    combined = result.stderr + result.stdout
    assert ("invalid choice" in combined or "error" in combined.lower() or
            "invalid_reason" in combined or "검증 실패" in combined), (
        f"에러 메시지 없음\nstderr: {result.stderr}\nstdout: {result.stdout}"
    )


def test_create_valid_reasons():
    """유효한 reason 값들 확인."""
    valid_reasons = ["interrupt", "complete", "takeover_request"]
    for reason in valid_reasons:
        task_id = TEST_TASK_REASONS[reason]
        handoff_path = WORKTREE / "memory" / "handoffs" / f"{task_id}.json"
        if handoff_path.exists():
            handoff_path.unlink()

        result = _run_handoff([
            "--task", task_id,
            "--reason", reason,
            "--bot", "dev4",
        ])

        try:
            assert result.returncode == 0, (
                f"유효한 reason '{reason}' 실패\nstdout: {result.stdout}\nstderr: {result.stderr}"
            )
            data = json.loads(handoff_path.read_text(encoding="utf-8"))
            assert data["handoff_reason"] == reason
        finally:
            if handoff_path.exists():
                handoff_path.unlink()
