"""task-2693 regression: callback authority 4-source validator
(PR #152 hardening #4 회장 verbatim 필수 4-요구 #4).

검증 대상: utils.callback_authority_4source_validator.validate
모든 verdict classification 케이스 1:1 매칭.
"""
from __future__ import annotations

from typing import Any, Dict, Optional

import importlib.util
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):
    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
    mod = importlib.util.module_from_spec(spec)
    sys.modules[modname] = mod
    spec.loader.exec_module(mod)
    return mod


_load_real(
    "utils.callback_authority_4source_validator",
    "utils/callback_authority_4source_validator.py",
)

from utils.callback_authority_4source_validator import (  # noqa: E402
    ACTUAL_CRON_OWNER_NOT_ANU,
    AUTHORITATIVE_4SOURCE_OK,
    ENVELOPE_3SID_MISMATCH,
    ENVELOPE_OWNER_NOT_ANU,
    SCHEDULE_HISTORY_SID_MISMATCH,
    SCHEDULE_HISTORY_STATUS_FAIL,
    VALIDATOR_SCHEMA,
    validate,
)

ANU = "c119085addb0f8b7"
SID = "53e89540-5bed-4692-a726-ed857820758a"
SID2 = "11111111-2222-3333-4444-555555555555"


def _env(
    chair: Optional[str] = SID,
    collector: Optional[str] = SID,
    delivery: Optional[str] = SID,
    owner: Optional[str] = ANU,
) -> Dict[str, Any]:
    return {
        "owner_key": owner,
        "chair_facing_session_id": chair,
        "collector_session_id": collector,
        "delivery_session_id": delivery,
    }


def test_schema_token_stable():
    assert VALIDATOR_SCHEMA == "utils.callback_authority_4source_validator.v1"


def test_authoritative_4source_ok():
    v = validate(
        envelope=_env(),
        actual_cron_owner_key=ANU,
        schedule_history_record={"status": "ok", "chair_facing_session_id": SID},
    )
    assert v.classification == AUTHORITATIVE_4SOURCE_OK, v
    assert v.passed is True


def test_envelope_owner_missing():
    v = validate(
        envelope=_env(owner=None),
        actual_cron_owner_key=ANU,
        schedule_history_record={"status": "ok"},
    )
    assert v.classification == ENVELOPE_OWNER_NOT_ANU, v
    assert v.passed is False


def test_actual_cron_owner_missing():
    v = validate(
        envelope=_env(),
        actual_cron_owner_key=None,
        schedule_history_record={"status": "ok"},
    )
    assert v.classification == ACTUAL_CRON_OWNER_NOT_ANU, v


def test_envelope_3sid_mismatch_collector_diff():
    v = validate(
        envelope=_env(collector=SID2),
        actual_cron_owner_key=ANU,
        schedule_history_record={"status": "ok"},
    )
    assert v.classification == ENVELOPE_3SID_MISMATCH, v


def test_envelope_3sid_mismatch_delivery_diff():
    v = validate(
        envelope=_env(delivery=SID2),
        actual_cron_owner_key=ANU,
        schedule_history_record={"status": "ok"},
    )
    assert v.classification == ENVELOPE_3SID_MISMATCH, v


def test_envelope_3sid_mismatch_missing_field():
    v = validate(
        envelope=_env(collector=""),
        actual_cron_owner_key=ANU,
        schedule_history_record={"status": "ok"},
    )
    assert v.classification == ENVELOPE_3SID_MISMATCH, v


def test_schedule_history_status_cancelled_fail():
    v = validate(
        envelope=_env(),
        actual_cron_owner_key=ANU,
        schedule_history_record={"status": "cancelled"},
    )
    assert v.classification == SCHEDULE_HISTORY_STATUS_FAIL, v


def test_schedule_history_status_error_fail():
    v = validate(
        envelope=_env(),
        actual_cron_owner_key=ANU,
        schedule_history_record={"status": "error"},
    )
    assert v.classification == SCHEDULE_HISTORY_STATUS_FAIL, v


def test_schedule_history_sid_mismatch():
    v = validate(
        envelope=_env(),
        actual_cron_owner_key=ANU,
        schedule_history_record={"status": "ok", "chair_facing_session_id": SID2},
    )
    assert v.classification == SCHEDULE_HISTORY_SID_MISMATCH, v


def test_schedule_history_missing_sid_field_still_passes_when_status_ok():
    # schedule_history 가 chair_facing_session_id 필드를 갖지 않아도 status=ok 면 PASS.
    v = validate(
        envelope=_env(),
        actual_cron_owner_key=ANU,
        schedule_history_record={"status": "ok"},
    )
    assert v.classification == AUTHORITATIVE_4SOURCE_OK, v


def test_non_dict_envelope_safe():
    v = validate(
        envelope=None,
        actual_cron_owner_key=ANU,
        schedule_history_record={"status": "ok"},
    )
    assert v.classification == ENVELOPE_OWNER_NOT_ANU, v


def test_non_dict_schedule_history_safe():
    # schedule_history_record=None 이면 sh_status=None != 'ok' → SCHEDULE_HISTORY_STATUS_FAIL
    v = validate(
        envelope=_env(),
        actual_cron_owner_key=ANU,
        schedule_history_record=None,
    )
    assert v.classification == SCHEDULE_HISTORY_STATUS_FAIL, v
