"""helper enforce API integration 회귀 테스트 (task-2694+1 MT-7).

assert_normal_callback_actually_registered → validator + marker 결합 검증.
회장 verbatim 핵심: envelope-only completion 차단 + FAIL시 marker 자동 발행.

NOTE: tests/dispatch/ 디렉토리가 dispatch 네임스페이스를 shadow 하기 때문에
worktree 본 dispatch.normal_fallback_callback_helper 를 importlib spec 으로
직접 로드한다 (test_callback_runtime_enforcement_2626.py 와 동일 패턴).
"""

from __future__ import annotations

import importlib.util
import json
import os
import sys
from pathlib import Path

_ROOT = Path(__file__).resolve().parents[3]
if str(_ROOT) not in sys.path:
    sys.path.insert(0, str(_ROOT))


def _load_real(modname: str, relpath: str):
    """worktree 본 모듈을 importlib spec 으로 강제 로드 (캐시/shadow 우회)."""
    existing = sys.modules.get(modname)
    if existing is not None and getattr(existing, "__file__", "").endswith(relpath):
        return existing
    spec = importlib.util.spec_from_file_location(modname, _ROOT / relpath)
    assert spec is not None and spec.loader is not None, (
        f"cannot load {modname} from {_ROOT / relpath}"
    )
    mod = importlib.util.module_from_spec(spec)
    sys.modules[modname] = mod
    spec.loader.exec_module(mod)
    return mod


# worktree 본 dependency chain 강제 로드 (shadow/cache 모두 우회)
_load_real(
    "utils.normal_callback_registration_validator",
    "utils/normal_callback_registration_validator.py",
)
_load_real(
    "utils.callback_registration_marker",
    "utils/callback_registration_marker.py",
)
_load_real("dispatch.callback_owner_enforcer", "dispatch/callback_owner_enforcer.py")
_helper_mod = _load_real(
    "dispatch.normal_fallback_callback_helper",
    "dispatch/normal_fallback_callback_helper.py",
)

ENFORCE_PASS = _helper_mod.ENFORCE_PASS
assert_normal_callback_actually_registered = (
    _helper_mod.assert_normal_callback_actually_registered
)


# --------------------------------------------------------------------------- #
# Helpers
# --------------------------------------------------------------------------- #


def _write_envelope(
    tmp_path,
    task_id: str,
    schedule_id: str,
    schedule_type: str = "cron_once",
    owner_key: str = "c119085addb0f8b7",
    chair_facing_sid: str = "53e89540-5bed-4692-a726-ed857820758a",
) -> str:
    env = {
        "schema": "schemas.anu_normal_callback_envelope_v1",
        "task_id": task_id,
        "schedule_id": schedule_id,
        "schedule_type": schedule_type,
        "owner_key": owner_key,
        "chat_id": "6937032012",
        "chair_facing_sid": chair_facing_sid,
        "emitted_at": "2026-05-27T00:00:00Z",
    }
    p = tmp_path / f"{task_id}.envelope.json"
    p.write_text(json.dumps(env), encoding="utf-8")
    return str(p)


# --------------------------------------------------------------------------- #
# Tests
# --------------------------------------------------------------------------- #


def test_envelope_only_fails_and_emits_marker(tmp_path):
    """envelope 만 있고 schedule_history/inbound 없을 때 FAIL + marker 발행.

    회장 verbatim 핵심 목표: envelope-only completion 코드 단계에서 차단.
    """
    env_path = _write_envelope(tmp_path, task_id="task-eo", schedule_id="sid-eo")
    events_dir = str(tmp_path / "events")
    os.makedirs(events_dir, exist_ok=True)
    result = assert_normal_callback_actually_registered(
        task_id="task-eo",
        envelope_path=env_path,
        events_dir=events_dir,
    )
    assert result.ok is False
    assert result.verdict != ENFORCE_PASS
    assert result.marker_path is not None
    assert os.path.exists(result.marker_path), (
        f"marker file should exist at {result.marker_path}"
    )
    # marker payload sanity
    with open(result.marker_path, "r", encoding="utf-8") as fp:
        payload = json.load(fp)
    assert payload["task_id"] == "task-eo"
    assert payload["hold_for_chair"] is True


def test_blocked_schedule_type_fails_and_emits_marker(tmp_path):
    """schedule_type=to_be_registered_by_finish_task_sh → FAIL + marker.

    task-2693 사고 박제 어구. helper 표면에서도 차단되어야 함.
    """
    env_path = _write_envelope(
        tmp_path,
        task_id="task-blk-int",
        schedule_id="sid-blk",
        schedule_type="to_be_registered_by_finish_task_sh",
    )
    events_dir = str(tmp_path / "events")
    os.makedirs(events_dir, exist_ok=True)
    result = assert_normal_callback_actually_registered(
        task_id="task-blk-int",
        envelope_path=env_path,
        events_dir=events_dir,
    )
    assert result.ok is False
    assert result.marker_path is not None
    assert os.path.exists(result.marker_path)
    # 박제 어구가 reason 에 반영되어야 함
    assert any(
        "schedule_type" in r.lower() or "blocked" in r.lower() for r in result.reasons
    ), f"blocked schedule_type reason 누락: {result.reasons}"


def test_no_marker_when_emit_disabled(tmp_path):
    """emit_marker_on_fail=False → FAIL 이어도 marker 미발행.

    downstream consumer 가 marker 발행을 자체 제어하고 싶을 때의 선택지.
    """
    env_path = _write_envelope(tmp_path, task_id="task-nomark", schedule_id="sid-nm")
    events_dir = str(tmp_path / "events")
    os.makedirs(events_dir, exist_ok=True)
    result = assert_normal_callback_actually_registered(
        task_id="task-nomark",
        envelope_path=env_path,
        events_dir=events_dir,
        emit_marker_on_fail=False,
    )
    assert result.ok is False
    assert result.marker_path is None, (
        f"marker_path should be None when emit disabled, got {result.marker_path}"
    )


def test_envelope_missing_fails_and_emits_marker(tmp_path):
    """envelope 파일 자체 없으면 FAIL + marker (envelope-only PASS 0% 보장)."""
    events_dir = str(tmp_path / "events")
    os.makedirs(events_dir, exist_ok=True)
    result = assert_normal_callback_actually_registered(
        task_id="task-nofile",
        envelope_path=str(tmp_path / "does-not-exist.json"),
        events_dir=events_dir,
    )
    assert result.ok is False
    assert result.marker_path is not None
    assert os.path.exists(result.marker_path)


def test_task_id_mismatch_fails_and_emits_marker(tmp_path):
    """stale envelope (task_id mismatch) → FAIL + marker."""
    env_path = _write_envelope(
        tmp_path, task_id="task-other", schedule_id="sid-x"
    )
    events_dir = str(tmp_path / "events")
    os.makedirs(events_dir, exist_ok=True)
    result = assert_normal_callback_actually_registered(
        task_id="task-mine",  # envelope.task_id == "task-other"
        envelope_path=env_path,
        events_dir=events_dir,
    )
    assert result.ok is False
    assert result.marker_path is not None
    assert os.path.exists(result.marker_path)
    assert any(
        "task_id" in r.lower() or "mismatch" in r.lower() for r in result.reasons
    ), f"task_id mismatch reason 누락: {result.reasons}"
