"""Hier-Replace-Diagnose-1 c5 — corpus_variant dispatcher 단위 테스트.

가드:
  1. _resolve_corpus_variant — slug→view, unknown ValueError, None→None
  2. CORPUS_VARIANT_MAP — 3 slug 1:1
  3. _VALID_CHUNKS_TABLE — 측정 뷰 3종 허용 + junk/injection 거부
"""
from __future__ import annotations

import logging
import os
import sys

import pytest

# logs/llm_gate.log root 소유 → import 시 PermissionError safe-wrap (test_query_rewriter 패턴)
_orig = logging.FileHandler
logging.FileHandler = lambda f, *a, **k: (_orig(f, *a, **k) if _try(f) else logging.NullHandler())  # type: ignore


def _try(f):
    try:
        open(f, "a").close()
        return True
    except Exception:
        return False


os.environ.setdefault("DATABASE_URL", "postgresql+asyncpg://test:test@localhost:5432/test")
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "app"))

from services.search import retrieval_service as rs


def test_resolve_valid_slugs():
    assert rs._resolve_corpus_variant("prehier") == "corpus_chunks_prehier"
    assert rs._resolve_corpus_variant("hier_sim_raw") == "corpus_chunks_hier_sim_raw"
    assert rs._resolve_corpus_variant("hier_sim_clean") == "corpus_chunks_hier_sim_clean"


def test_resolve_none():
    assert rs._resolve_corpus_variant(None) is None


@pytest.mark.parametrize("bad", ["", "hier", "corpus_chunks", "prehier; DROP TABLE", "hier_sim", "HIER_SIM_CLEAN"])
def test_resolve_unknown_raises(bad):
    with pytest.raises(ValueError, match="unknown_corpus_variant"):
        rs._resolve_corpus_variant(bad)


def test_variant_map_keys():
    assert set(rs.CORPUS_VARIANT_MAP) == {"prehier", "hier_sim_raw", "hier_sim_clean"}


@pytest.mark.parametrize("view", [
    "corpus_chunks_prehier", "corpus_chunks_hier_sim_raw", "corpus_chunks_hier_sim_clean",
    "document_chunks", "corpus_chunks", "document_chunks_cand_me5",
])
def test_valid_chunks_table_allows(view):
    assert rs._VALID_CHUNKS_TABLE.match(view)


@pytest.mark.parametrize("bad", [
    "corpus_chunks_prehier; DROP TABLE x", "corpus_chunks_hier_sim", "documents",
    "corpus_chunks_evil", "'; DELETE--", "corpus_chunks_hier_sim_cleanX",
])
def test_valid_chunks_table_rejects(bad):
    assert not rs._VALID_CHUNKS_TABLE.match(bad)


def test_all_mapped_views_pass_allowlist():
    # resolver 가 내놓는 모든 뷰는 SQL interpolation gate 통과해야 함
    for v in rs.CORPUS_VARIANT_MAP.values():
        assert rs._VALID_CHUNKS_TABLE.match(v)
