"""Phase 4-B v1 환각 가드 정규식 단위 테스트 — ship gate.

worker 와 같은 모듈을 import 해 검증. plan 의 검증 D 케이스 (허용 5 + 차단 7).
"""

from __future__ import annotations

import sys
from pathlib import Path

# 프로젝트 루트의 app/ 를 import path 에 추가 (Document Server 패턴)
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "app"))

from services.study.session_summary_guard import (  # noqa: E402
    GUARD_PATTERN,
    calibrate_confidence,
    normalize_confidence,
)


# ─── GUARD_PATTERN 허용 케이스 (search() == None 이어야 함) ───

ALLOWED_CASES = [
    "오답 5건이 있었습니다.",
    "모르겠음 83건이 남았습니다.",
    "배관 영역에서 흔들린 것으로 보입니다.",
    "같은 영역 문제를 더 풀어보세요.",
    "정답을 다시 한 번 확인해보세요.",
]


# ─── GUARD_PATTERN 차단 케이스 (search() != None 이어야 함) ───

BLOCKED_CASES = [
    "정답률 16%였습니다.",
    "최근 5일 동안 약했습니다.",
    "지난 7일간 비슷한 실수가 반복됐습니다.",
    "5~10문항을 더 풀어보세요.",
    "2026-05-02 기준으로 보면...",
    "5월 2일 이후 흐름은...",
    "지난 7회차에서 반복됐습니다.",
]


def test_guard_pattern_allows_normal_summary():
    for case in ALLOWED_CASES:
        match = GUARD_PATTERN.search(case)
        assert match is None, f"false positive: {case!r} matched {match!r}"


def test_guard_pattern_blocks_numeric_hallucination():
    for case in BLOCKED_CASES:
        match = GUARD_PATTERN.search(case)
        assert match is not None, f"false negative: {case!r} not matched"


def test_normalize_confidence_standard_values():
    for v in ("high", "medium", "low"):
        assert normalize_confidence(v) == v
        assert normalize_confidence(v.upper()) == v
        assert normalize_confidence(f"  {v}  ") == v


def test_normalize_confidence_nonstandard_values():
    for v in ("unknown", "mid", "maybe", "", "true", None, 123, [], {}):
        assert normalize_confidence(v) == "low"


# ─── Phase 4-D calibrate_confidence — 자료 부족 토픽 cap ───

def test_calibrate_confidence_no_evidence_caps_to_low():
    # 문서 0 + ready ai_explanation 0 → cap 'low'
    assert calibrate_confidence("high", ctx_docs_count=0, ready_explanation_count=0) == "low"
    assert calibrate_confidence("medium", ctx_docs_count=0, ready_explanation_count=0) == "low"
    assert calibrate_confidence("low", ctx_docs_count=0, ready_explanation_count=0) == "low"


def test_calibrate_confidence_only_explanations_caps_to_medium():
    # 문서 0 + ready ai_explanation 있음 → cap 'medium'
    assert calibrate_confidence("high", ctx_docs_count=0, ready_explanation_count=3) == "medium"
    assert calibrate_confidence("medium", ctx_docs_count=0, ready_explanation_count=3) == "medium"
    assert calibrate_confidence("low", ctx_docs_count=0, ready_explanation_count=3) == "low"


def test_calibrate_confidence_with_documents_passthrough():
    # 문서 1건 이상 → 모델 값 그대로 통과
    assert calibrate_confidence("high", ctx_docs_count=2, ready_explanation_count=0) == "high"
    assert calibrate_confidence("medium", ctx_docs_count=1, ready_explanation_count=0) == "medium"
    assert calibrate_confidence("low", ctx_docs_count=5, ready_explanation_count=10) == "low"


def test_calibrate_confidence_normalizes_invalid_first():
    # 비표준 값은 normalize_confidence 가 'low' 로 박은 후 cap 적용 — 결과는 'low'
    assert calibrate_confidence("unknown", ctx_docs_count=0, ready_explanation_count=0) == "low"
    assert calibrate_confidence(None, ctx_docs_count=5, ready_explanation_count=5) == "low"


if __name__ == "__main__":
    # 직접 실행 시 모든 케이스 빠른 점검
    test_guard_pattern_allows_normal_summary()
    test_guard_pattern_blocks_numeric_hallucination()
    test_normalize_confidence_standard_values()
    test_normalize_confidence_nonstandard_values()
    test_calibrate_confidence_no_evidence_caps_to_low()
    test_calibrate_confidence_only_explanations_caps_to_medium()
    test_calibrate_confidence_with_documents_passthrough()
    test_calibrate_confidence_normalizes_invalid_first()
    print("OK")
