"""regression: task-2575 — record_lock_sha() 동작 검증.

검증 항목:
1. 신규 lock 파일 생성
2. 기존 lock 파일 갱신 (기존 키 보존 + lock_sha 추가)
3. lock_sha 재갱신 (마지막 SHA로 덮어씀)
4. invalid SHA 거부 (길이 오류, 비-hex 문자)
5. atomic write 확인 (.tmp 잔존 없음)
"""
import json
import sys
from pathlib import Path

import pytest

SCRIPTS = Path(__file__).resolve().parents[2] / "scripts"
sys.path.insert(0, str(SCRIPTS))

from taskctl_start import record_lock_sha  # type: ignore[import-not-found]  # noqa: E402

VALID_SHA = "a" * 40  # 40자리 hex


# ---------------------------------------------------------------------------
# 테스트 1: 신규 lock 파일 생성
# ---------------------------------------------------------------------------

def test_new_lock_file_created(tmp_path):
    result = record_lock_sha(tmp_path, "task-9001", VALID_SHA)

    assert result["status"] == "created"
    lock_path = Path(result["lock_path"])
    assert lock_path.exists()

    data = json.loads(lock_path.read_text())
    assert data["lock_sha"] == VALID_SHA
    assert data["task_id"] == "task-9001"


# ---------------------------------------------------------------------------
# 테스트 2: 기존 lock 파일 갱신 — 기존 키 보존 + lock_sha 추가
# ---------------------------------------------------------------------------

def test_existing_lock_file_updated_keys_preserved(tmp_path):
    # 사전 lock 파일 생성 (5키 포함)
    locks_dir = tmp_path / ".tasks" / "locks"
    locks_dir.mkdir(parents=True)
    existing_data = {
        "task_id": "task-9002",
        "bot": "enki",
        "branch": "task/9002-dev5",
        "worktree": "/home/jay/workspace/.worktrees/task-9002-dev5",
        "pid": 12345,
        "started_at": "2025-01-01T00:00:00",
        "heartbeat_timestamp": "2025-01-01T01:00:00",
    }
    lock_file = locks_dir / "task-9002.lock"
    lock_file.write_text(json.dumps(existing_data))

    result = record_lock_sha(tmp_path, "task-9002", VALID_SHA)

    assert result["status"] == "updated"
    data = json.loads(lock_file.read_text())

    # 기존 키 보존 확인
    assert data["bot"] == "enki"
    assert data["branch"] == "task/9002-dev5"
    assert data["worktree"] == "/home/jay/workspace/.worktrees/task-9002-dev5"
    assert data["pid"] == 12345
    assert data["started_at"] == "2025-01-01T00:00:00"
    assert data["heartbeat_timestamp"] == "2025-01-01T01:00:00"

    # lock_sha 추가 확인
    assert data["lock_sha"] == VALID_SHA


# ---------------------------------------------------------------------------
# 테스트 3: lock_sha 재갱신 — 마지막 SHA로 덮어씀
# ---------------------------------------------------------------------------

def test_lock_sha_overwritten_on_second_call(tmp_path):
    sha1 = "1" * 40
    sha2 = "2" * 40

    record_lock_sha(tmp_path, "task-9003", sha1)
    result = record_lock_sha(tmp_path, "task-9003", sha2)

    lock_path = Path(result["lock_path"])
    data = json.loads(lock_path.read_text())

    assert data["lock_sha"] == sha2, "마지막 SHA로 갱신되어야 함"
    assert result["lock_sha"] == sha2


# ---------------------------------------------------------------------------
# 테스트 4: invalid SHA 거부
# ---------------------------------------------------------------------------

@pytest.mark.parametrize("bad_sha,reason", [
    ("a" * 39, "length_39"),   # 39자리
    ("a" * 41, "length_41"),   # 41자리
    ("g" * 40, "non_hex"),     # 비-hex 문자
    ("A" * 40, "uppercase"),   # 대문자 hex (소문자만 허용)
    ("",       "empty"),       # 빈 문자열
])
def test_invalid_sha_rejected(tmp_path, bad_sha, reason):
    result = record_lock_sha(tmp_path, "task-9004", bad_sha)

    assert result["status"] == "skipped", f"[{reason}] status must be 'skipped'"

    # lock 파일이 생성되지 않아야 함
    lock_path = tmp_path / ".tasks" / "locks" / "task-9004.lock"
    assert not lock_path.exists(), f"[{reason}] lock 파일이 생성되면 안 됨"


def test_invalid_sha_does_not_overwrite_existing(tmp_path):
    """기존 lock 파일이 있을 때 invalid SHA → 파일 미갱신."""
    # 정상 SHA로 먼저 기록
    record_lock_sha(tmp_path, "task-9005", VALID_SHA)

    # invalid SHA로 시도
    bad_sha = "z" * 40
    result = record_lock_sha(tmp_path, "task-9005", bad_sha)

    assert result["status"] == "skipped"

    lock_path = tmp_path / ".tasks" / "locks" / "task-9005.lock"
    data = json.loads(lock_path.read_text())
    assert data["lock_sha"] == VALID_SHA, "기존 lock_sha가 변경되면 안 됨"


# ---------------------------------------------------------------------------
# 테스트 5: atomic write — .tmp 잔존 없음
# ---------------------------------------------------------------------------

def test_no_tmp_file_remains_after_write(tmp_path):
    record_lock_sha(tmp_path, "task-9006", VALID_SHA)

    locks_dir = tmp_path / ".tasks" / "locks"
    tmp_files = list(locks_dir.glob("*.tmp"))
    assert tmp_files == [], f".tmp 잔존 파일이 있음: {tmp_files}"
