"""utils/sanitize_gate.py 테스트"""

import sys
from pathlib import Path

import pytest

# workspace를 sys.path에 추가 (conftest.py에서도 처리하지만 명시적으로 보장)
_WORKSPACE = Path(__file__).parent.parent
if str(_WORKSPACE) not in sys.path:
    sys.path.insert(0, str(_WORKSPACE))

from utils.sanitize_gate import (
    SANITIZE_PATTERNS,
    generate_sanitize_report,
    sanitize_file_content,
    sanitize_text,
    should_sanitize,
)

# ---------------------------------------------------------------------------
# MT-1: sanitize_gate.py 테스트
# ---------------------------------------------------------------------------


class TestShouldSanitize:
    """should_sanitize() 레벨별 동작 검증"""

    def test_should_sanitize_levels(self):
        """level 0~4에 대해 should_sanitize() 동작 검증:
        0, 1, 2 → False / 3, 4 → True
        """
        assert should_sanitize(0) is False
        assert should_sanitize(1) is False
        assert should_sanitize(2) is False
        assert should_sanitize(3) is True
        assert should_sanitize(4) is True


class TestSanitizeText:
    """sanitize_text() PII 마스킹 검증"""

    def test_sanitize_text_rrn(self):
        """주민등록번호 마스킹 검증"""
        text = "주민번호: 900101-1234567"
        masked, detections = sanitize_text(text)

        assert "[RRN-REDACTED]" in masked
        assert len(detections) == 1
        assert detections[0]["type"] == "rrn"

    def test_sanitize_text_phone(self):
        """전화번호 마스킹 검증"""
        text = "연락처: 010-1234-5678"
        masked, detections = sanitize_text(text)

        assert "[PHONE-REDACTED]" in masked
        assert len(detections) == 1

    def test_sanitize_text_email(self):
        """이메일 마스킹 검증"""
        text = "이메일: test@example.com"
        masked, _detections = sanitize_text(text)

        assert "[EMAIL-REDACTED]" in masked

    def test_sanitize_text_apikey(self):
        """API 키 마스킹 검증"""
        text = "키: sk-1234567890abcdef"
        masked, _detections = sanitize_text(text)

        assert "[APIKEY-REDACTED]" in masked

    def test_sanitize_text_policy(self):
        """보험 증권번호 마스킹 검증"""
        text = "증권: AB12345678"
        masked, _detections = sanitize_text(text)

        assert "[POLICY-REDACTED]" in masked

    def test_sanitize_text_multiple(self):
        """여러 PII가 섞인 텍스트 검증"""
        text = "주민번호: 900101-1234567, 연락처: 010-1234-5678, 이메일: test@example.com"
        _masked, detections = sanitize_text(text)

        assert len(detections) >= 3

    def test_sanitize_text_no_pii(self):
        """PII 없는 텍스트 — detections 0건, 원본 그대로 반환"""
        original = "안녕하세요. 오늘 날씨가 좋습니다."
        masked, detections = sanitize_text(original)

        assert len(detections) == 0
        assert masked == original


class TestSanitizeFileContent:
    """sanitize_file_content() 파일 읽기 테스트"""

    def test_sanitize_file_content(self, tmp_path):
        """실제 파일 읽기 테스트 — tmpdir에 PII 포함된 파일 생성 후 마스킹 확인"""
        pii_file = tmp_path / "pii_sample.txt"
        pii_file.write_text(
            "이름: 홍길동\n주민번호: 900101-1234567\n연락처: 010-9876-5432\n",
            encoding="utf-8",
        )

        masked, detections = sanitize_file_content(str(pii_file))

        assert "[RRN-REDACTED]" in masked
        assert "[PHONE-REDACTED]" in masked
        assert len(detections) >= 2

    def test_sanitize_file_not_found(self):
        """존재하지 않는 파일 → FileNotFoundError 예외"""
        with pytest.raises(FileNotFoundError):
            sanitize_file_content("/tmp/nonexistent_file_xyz_12345.txt")


class TestGenerateSanitizeReport:
    """generate_sanitize_report() 리포트 생성 검증"""

    def test_generate_report_empty(self):
        """detections가 빈 리스트일 때 '감지된 PII 없음' 메시지"""
        report = generate_sanitize_report([])

        assert "감지된 PII 없음" in report

    def test_generate_report_with_detections(self):
        """detections에 여러 항목이 있을 때 markdown 테이블 생성 확인"""
        detections = [
            {
                "type": "rrn",
                "description": "주민등록번호",
                "original": "900101-1234567",
                "replacement": "[RRN-REDACTED]",
            },
            {
                "type": "phone",
                "description": "전화번호",
                "original": "010-1234-5678",
                "replacement": "[PHONE-REDACTED]",
            },
        ]
        report = generate_sanitize_report(detections)

        # markdown 테이블 헤더 확인
        assert "|" in report
        # 유형 정보 포함 확인
        assert "rrn" in report
        assert "phone" in report
        # 건수 정보 확인
        assert "2" in report


class TestPatternsCompleteness:
    """SANITIZE_PATTERNS 완전성 검증"""

    def test_patterns_completeness(self):
        """SANITIZE_PATTERNS에 6개 패턴(rrn, phone, email, apikey, account, policy) 존재 확인"""
        required_keys = {"rrn", "phone", "email", "apikey", "account", "policy"}
        assert required_keys.issubset(set(SANITIZE_PATTERNS.keys()))


# ---------------------------------------------------------------------------
# MT-2: gate_instructions.py 테스트
# ---------------------------------------------------------------------------

from prompts.gate_instructions import format_for_prompt


class TestGateInstructionsSanitize:
    """format_for_prompt()의 sanitize 문자열 포함 여부 검증"""

    def test_gate_instructions_sanitize_lv3(self):
        """format_for_prompt(3) 결과에 'sanitize' 문자열 포함 확인"""
        result = format_for_prompt(3)
        assert "sanitize" in result.lower()

    def test_gate_instructions_sanitize_lv4(self):
        """format_for_prompt(4) 결과에 'sanitize' 문자열 포함 확인"""
        result = format_for_prompt(4)
        assert "sanitize" in result.lower()

    def test_gate_instructions_no_sanitize_lv2(self):
        """format_for_prompt(2) 결과에 'sanitize' 문자열 미포함 확인"""
        result = format_for_prompt(2)
        assert "sanitize" not in result.lower()
