# -*- coding: utf-8 -*-
"""task-2686 regression — anu_normal_callback_envelope_v1 schema 3 field 검증.

회장 verbatim 5번 (★ envelope schema 3 field 추가):
  - chair_facing_session_id (필수)
  - collector_session_id (선택, 누락 가능 — Tier 1 doctrine 호환)
  - delivery_session_id (선택, 누락 가능)

schema 파일이 위 3 field 정의를 포함하는지 / required 에 chair_facing_session_id
가 들어있는지 / UUID pattern 이 cokacdir --session UUID 형식과 일치하는지 검증.
"""
from __future__ import annotations

import json
from pathlib import Path

import pytest

_ROOT = Path(__file__).resolve().parents[3]
_SCHEMA_PATH = _ROOT / "schemas" / "anu_normal_callback_envelope_v1.json"


@pytest.fixture(scope="module")
def schema() -> dict:
    assert _SCHEMA_PATH.exists(), f"schema file missing: {_SCHEMA_PATH}"
    return json.loads(_SCHEMA_PATH.read_text(encoding="utf-8"))


def test_schema_has_three_session_fields(schema):
    props = schema.get("properties", {})
    assert "chair_facing_session_id" in props, "회장 verbatim 5번 필드 1/3 누락"
    assert "collector_session_id" in props, "회장 verbatim 5번 필드 2/3 누락"
    assert "delivery_session_id" in props, "회장 verbatim 5번 필드 3/3 누락"


def test_schema_session_fields_use_uuid_pattern(schema):
    props = schema["properties"]
    uuid_re = (
        "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-"
        "[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
    )
    for field_name in (
        "chair_facing_session_id",
        "collector_session_id",
        "delivery_session_id",
    ):
        assert props[field_name].get("pattern") == uuid_re, (
            f"{field_name} pattern 이 UUID 형식과 불일치: {props[field_name]}"
        )


def test_schema_chair_facing_is_required(schema):
    # reconcile: PR #155 base 는 chair_facing_sid (단수) 를 required 로 사용.
    # PR #152 long-form chair_facing_session_id 는 alias optional field.
    # 둘 중 하나가 required 에 있으면 PASS (명명 정합 — PR #155 절대 훼손 금지).
    required = set(schema.get("required", []))
    assert "chair_facing_sid" in required or "chair_facing_session_id" in required, (
        "chair_facing 세션 식별자(단수 chair_facing_sid 또는 long-form chair_facing_session_id)"
        "가 required 여야 함 (PR #155 base 는 chair_facing_sid 단수 required — 명명 정합)."
    )


def test_schema_owner_key_pinned_to_anu(schema):
    """ANCHOR-2 (key authority != session continuity) — owner_key 는 ANU key 형태 강제."""
    # reconcile: PR #155 base 는 const 대신 pattern(^[0-9a-f]{16}$) 을 사용.
    # self-key fail-closed 는 enforce/validator 가 담당 — schema 는 hex 형태만 보장.
    owner = schema["properties"]["owner_key"]
    assert owner.get("pattern") == "^[0-9a-f]{16}$", (
        "owner_key 는 16-char hex pattern 으로 ANU key 형태 강제 "
        "(PR #155 base 는 const 대신 pattern — self-key fail-closed 는 enforce/validator 가 담당)."
    )


def test_schema_collector_role_anu_only(schema):
    role = schema["properties"]["collector_role"]
    assert role.get("enum") == ["ANU"], (
        "collector_role enum 은 ['ANU'] 단일 (회장 §10)."
    )


def test_schema_no_additional_properties(schema):
    """additionalProperties=true → PR #155+PR #152 혼합 envelope 의 trace 필드 허용."""
    # reconcile: PR #155 base schema 는 PR #155+PR #152 혼합 envelope 의 trace 필드
    # 허용을 위해 additionalProperties:true 를 유지 (3 SID 는 명시 UUID pattern 으로
    # 검증 — PR #155 절대 훼손 금지).
    assert schema.get("additionalProperties") is True, (
        "PR #155 base schema 는 PR #155+PR #152 혼합 envelope 의 trace 필드 허용을 위해 "
        "additionalProperties:true 를 유지 (3 SID 는 명시 UUID pattern 으로 검증 — PR #155 절대 훼손 금지)."
    )
