"""tests/regression/test_escalation_marker.py — Group 6 (4건, §2.A 18-21).

task-2472 regression: escalation marker 발행 차단 검증.

19. test_shell_raw_emit_blocked_in_finish_task_sh
20. test_emit_without_payload_rejected
21. test_zero_byte_escalation_marker_rejected
22. test_state_file_missing_blocks_done_or_merge
"""
from __future__ import annotations

import importlib.util
import re
import sys
from pathlib import Path

WORKTREE = Path(__file__).resolve().parents[2]


def _load(mod_name: str, rel: str):
    path = WORKTREE / rel
    spec = importlib.util.spec_from_file_location(mod_name, str(path))
    assert spec is not None and spec.loader is not None, f"spec load 실패: {path}"
    mod = importlib.util.module_from_spec(spec)
    sys.modules[mod_name] = mod
    spec.loader.exec_module(mod)
    return mod


em = _load("escalation_marker_g6", "scripts/escalation_marker.py")
scg = _load("silent_corruption_guard_g6", "utils/silent_corruption_guard.py")


# ---------------------------------------------------------------------------
# Test 19 (§2.A-18): finish-task.sh에 raw `: > *.done.escalated` 0건 검증
# ---------------------------------------------------------------------------

def test_shell_raw_emit_blocked_in_finish_task_sh():
    """finish-task.sh에 raw shell emit `: > *.done.escalated` 패턴이 0건이어야 함."""
    script_path = WORKTREE / "scripts" / "finish-task.sh"
    assert script_path.exists(), f"finish-task.sh 없음: {script_path}"

    content = script_path.read_text(encoding="utf-8")
    # raw `: > ` 패턴 (done.escalated 또는 done.blocked 대상)
    raw_pattern = re.compile(
        r"^\s*:\s*>\s*.*\.done\.(escalated|blocked)",
        re.MULTILINE,
    )
    matches = raw_pattern.findall(content)
    assert len(matches) == 0, (
        f"finish-task.sh에 raw escalation emit 패턴 {len(matches)}건 발견 — task-2472 위반:\n"
        + "\n".join(m for m in raw_pattern.findall(content))
    )

    # escalation_marker.py 호출이 있는지 확인 (BLOCKED/ESCALATED case 대응)
    assert "escalation_marker.py" in content, (
        "finish-task.sh에 escalation_marker.py 호출이 없음 — task-2472 구현 누락"
    )


# ---------------------------------------------------------------------------
# Test 20 (§2.A-19): emit_escalation() 필수 필드 누락 → fail-closed
# ---------------------------------------------------------------------------

def test_emit_without_payload_rejected(tmp_path, monkeypatch):
    """emit_escalation() 호출 시 필수 필드 누락 → ok=False (fail-closed)."""
    # EVENTS_DIR과 AUDIT_DIR을 tmp_path로 override
    monkeypatch.setattr(em, "EVENTS_DIR", tmp_path / "events")
    monkeypatch.setattr(em, "AUDIT_DIR", tmp_path / "audit")
    monkeypatch.setattr(em, "ESCALATION_AUDIT_PATH", tmp_path / "audit" / "state-recovery.jsonl")

    # reason 없음 (빈 문자열)
    result = em.emit_escalation(
        task_id="task-2472-test",
        kind="escalated",
        reason="",  # 빈 문자열 → 필드 누락으로 처리
        source="test",
        blocking_condition="test-block",
        evidence_path="/dev/null",
    )

    assert result["ok"] is False, "reason 빈 문자열 → emit 거부 필수"
    assert "누락" in result["reason"] or "실패" in result["reason"]

    # blocking_condition 없음
    result2 = em.emit_escalation(
        task_id="task-2472-test2",
        kind="escalated",
        reason="valid reason",
        source="test",
        blocking_condition="",  # 빈 문자열
        evidence_path="/dev/null",
    )
    assert result2["ok"] is False, "blocking_condition 빈 문자열 → emit 거부 필수"


# ---------------------------------------------------------------------------
# Test 21 (§2.A-20): 0-byte .done.escalated → check_escalated_payload ok=False
# ---------------------------------------------------------------------------

def test_zero_byte_escalation_marker_rejected(tmp_path):
    """강제로 0-byte .done.escalated 생성 후 check_escalated_payload → ok=False."""
    escalated_path = tmp_path / "task-zero-byte-test.done.escalated"
    escalated_path.write_bytes(b"")  # 0-byte 파일 강제 생성

    result = scg.check_escalated_payload(escalated_path)

    assert result["ok"] is False, "0-byte escalated 파일 → fail-closed 필수"
    assert "0-byte" in result["reason"] or "0" in result["reason"]
    assert result["detail"]["size"] == 0


# ---------------------------------------------------------------------------
# Test 22 (§2.A-21): state 파일 없는 상태에서 check_state_file_present → ok=False
# ---------------------------------------------------------------------------

def test_state_file_missing_blocks_done_or_merge(tmp_path):
    """.tasks/state/{task_id}.json 없을 때 check_state_file_present → ok=False."""
    task_id = "task-no-state-22"

    # state 파일 만들지 않고 바로 check
    result = scg.check_state_file_present(task_id, workspace=tmp_path)

    assert result["ok"] is False, "state 파일 없으면 done/merge 차단 필수"
    assert "없음" in result["reason"] or "fail-closed" in result["reason"]
    assert result["detail"]["exists"] is False
