import json
import os
import csv
import logging
from pydantic import BaseModel

logger = logging.getLogger("uvicorn.error")

RAILWAY_TERMS_LIST: list[str] = []
RAILWAY_TERMS_DICT: dict[str, list[dict]] = {}

def load_terms_from_csv(file_path: str):
    """
    [Chapter 6.1] 대규모 도메인 사전(CSV) 안전 적재
    동음이의어(중복 키)를 허용하기 위해 List 형태로 Value를 저장하며,
    RapidFuzz 일괄 대조를 위한 중복 제거 리스트를 함께 생성합니다.
    """
    global RAILWAY_TERMS_LIST, RAILWAY_TERMS_DICT
    RAILWAY_TERMS_LIST.clear()
    RAILWAY_TERMS_DICT.clear()

    if not os.path.exists(file_path):
        raise FileNotFoundError(f"CSV 사전을 찾을 수 없습니다: {file_path}")

    # 인코딩 Fallback: utf-8-sig 우선, 실패 시 cp949
    try:
        with open(file_path, mode="r", encoding="utf-8-sig") as f:
            reader = csv.DictReader(f)
            rows = list(reader)
    except UnicodeDecodeError:
        logger.warning(f"UTF-8-SIG 디코딩 실패. CP949로 재시도합니다: {file_path}")
        with open(file_path, mode="r", encoding="cp949") as f:
            reader = csv.DictReader(f)
            rows = list(reader)

    unique_terms = set()
    count = 0

    for row in rows:
        keyword = row.get("용어명", "").strip()
        desc = row.get("내용", "").strip()
        category = row.get("관련분야", "").strip()

        if not keyword:
            continue

        unique_terms.add(keyword)
        if keyword not in RAILWAY_TERMS_DICT:
            RAILWAY_TERMS_DICT[keyword] = []
        
        RAILWAY_TERMS_DICT[keyword].append({
            "desc": desc,
            "category": category
        })
        count += 1

    RAILWAY_TERMS_LIST.extend(list(unique_terms))
    logger.info(f"✅ 대규모 사전 로드 완료: 총 {count}행 처리, 매칭 대상 {len(RAILWAY_TERMS_LIST)}단어 (파일: {file_path})")


# ── 화자 분류용 호출 부호 외부 정의 ──────────────────────────────────────────
# speaker_classifier.py가 이 목록을 임포트하여 사용합니다.
# 현장 호출 부호가 추가될 때 여기만 수정하면 전체 파이프라인에 반영됩니다.

CALLSIGNS_CONTROL: list[str] = [
    # ── 부산 도시철도 관제 호출 코드 ──
    "전철 보안", "전철 범일", "전철 호포", "전철 신평", "전철 관제", "전철 통제",
    "전철보안", "전철범일", "전철호포", "전철신평",
    # 관제사 특유 어구
    "진로 확인 부탁", "통과 허가", "신호진로 확인",
]

CALLSIGNS_TRAIN: list[str] = [
    # ── 차량/열차 유형 ──
    "모터카", "전기 모터카", "신호 모터카", "검측차", "검축차", "궤도 검측차",
    # 열차 발화 특유 어구
    "출발 합니다", "출발하겠습니다", "통과 하겠습니다", "통과하겠습니다",
    "확인하고 통과", "신호 확인 후 통과",
]

class DomainDictionary(BaseModel):
    stations: list[str] = [
        "다대포해수욕장", "다대포항", "낫개", "신장림", "장림", "동매", "신평", "하단", "당리", "사하", "괴정",
        "대티", "서대신", "동대신", "토성", "자갈치", "남포", "중앙", "노포", "범어사", "남산", "두실", "구서", "장전",
        "부산대", "온천장", "명륜", "동래", "교대", "연산", "시청", "양정", "부전", "서면", "범내골", "범일", "좌천", "부산진",
        "초량", "부산역"
    ]
    railway_terms: list[str] = [
        "모터카", "분기기", "신호기", "궤도", "검축차", "하선", "상선", "입고", "출고", "무전", "수신", "양호",
        "신호 모터카", "전기 모터카", "궤도 검측차"
    ]
    HARDCODED_FIXES: dict[str, str] = {
        "신호질로": "신호 진로",
        "멀티플": "멀티플 타이탬퍼"
    }

    def get_prompt(self) -> str:
        """STT 모델에 주입할 initial_prompt 문자열을 반환합니다."""
        return " ".join(self.stations + self.railway_terms)
    def post_process_correction(self, text: str, threshold: float = 85.0) -> str:
        """
        [Chapter 6.1 최적화 알고리즘]
        RapidFuzz를 사용하여 문장 내 특정 어절들을 사전 단어와 비교 후 
        오타로 판단되면 철도 전문 용어로 자동 교정합니다. (띄어쓰기 기준으로 토큰화)
        """
        from rapidfuzz import process, fuzz
        # RAILWAY_TERMS_LIST가 비어있으면 기본 하드코딩을 쓰고, 있으면 합침
        all_terms = self.stations + self.railway_terms
        if RAILWAY_TERMS_LIST:
            all_terms.extend(RAILWAY_TERMS_LIST)
        
        # 1. 하드코딩 교정 (단순 매칭/replace)
        for bad_word, good_word in self.HARDCODED_FIXES.items():
            text = text.replace(bad_word, good_word)
        
        words = text.split()
        corrected_words = []
        
        # 유효한 최적화를 위해 중복 제거
        unique_terms = list(set(all_terms))
        
        for word in words:
            # 특수 기호 경계 지우기 (단순화)
            clean_word = "".join(c for c in word if c.isalnum())
            best_match = None
            
            # 짧은 단어 무시 (길이 2 이상만 대조, CPU 최적화)
            if len(clean_word) >= 2 and unique_terms:
                match_result = process.extractOne(
                    clean_word, 
                    unique_terms, 
                    scorer=fuzz.WRatio, 
                    score_cutoff=threshold
                )
                if match_result:
                    best_match = match_result[0]
            
            if best_match:
                corrected_words.append(best_match)
            else:
                corrected_words.append(word)
                
        # 3. 추가 보정 (선택사항)
        for i, cw in enumerate(corrected_words):
            if "다대포" in cw and not cw.endswith("역") and not "해수욕" in cw:
                corrected_words[i] = cw + "역"
                
        return " ".join(corrected_words)

# 전역 인스턴스
domain_dict = DomainDictionary()
