"""
유연한 지식(Context) 제공자 패턴 모듈.
LLM Worker가 추출한 키워드를 받아 관련 지식 DB(또는 Mock)에서
추가 컨텍스트 딕셔너리를 반환합니다. 향후 RAG 서버로 코드 수정 없이 확장할 수 있습니다.
"""
from abc import ABC, abstractmethod
import logging
from typing import List, Dict, Any

from app.core.config import settings

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

class ContextProvider(ABC):
    """지식 제공자 추상 클래스"""
    @abstractmethod
    def get_extended_context(self, keywords: List[str]) -> List[Dict[str, Any]]:
        pass


class MockContextProvider(ContextProvider):
    """개발 및 데모를 위한 하드코딩된 Mock 지식 제공자"""
    def __init__(self):
        # 데모용 지식 딕셔너리
        self._mock_db = {
            "검측차": {
                "title": "검측차 (Inspection Train)",
                "desc": "선로, 전차선, 신호 등의 상태를 주행하며 실시간으로 점검하는 특수 목적 차량. 주로 야간 작업에 투입됨."
            },
            "다대포": {
                "title": "다대포 해수욕장역 (Dadaepo Beach)",
                "desc": "부산 도시철도 1호선의 종착역. 회차선 및 차량 유치선 존재."
            },
            "tcms": {
                "title": "TCMS (열차종합제어장치)",
                "desc": "Train Control and Monitoring System. 열차의 각종 주요 기기를 제어하고 실시간 상태를 감시, 진단하는 시스템."
            },
            "관제": {
                "title": "관제 센터 (Control Center)",
                "desc": "전체 철도 시스템의 운행 상황을 실시간 모니터링하고 통제, 지시를 내리는 종합 사령실."
            }
        }

    def get_extended_context(self, keywords: List[str]) -> List[Dict[str, Any]]:
        results = []
        found_keys = set()
        
        for kw in keywords:
            kw_lower = kw.lower()
            for key, val in self._mock_db.items():
                if key in found_keys:
                    continue
                # 키워드가 DB 키에 포함되거나, DB 키가 키워드에 포함된 경우 매칭
                if key.lower() in kw_lower or kw_lower in key.lower():
                    results.append({
                        "keyword": key,
                        "title": val["title"],
                        "desc": val["desc"]
                    })
                    found_keys.add(key)
        
        return results


class CSVContextProvider(ContextProvider):
    """
    [Chapter 6.1] 
    대규모 도메인 사전(CSV) 기반의 지식 제공자. O(1) 검색 최적화 및 
    동음이의어(리스트 Value) 중복 처리를 허용합니다.
    """
    def get_extended_context(self, keywords: List[str]) -> List[Dict[str, Any]]:
        from app.core.dictionary import RAILWAY_TERMS_DICT
        results = []
        found_keys = set()
        
        for kw in keywords:
            kw_clean = kw.strip()
            if not kw_clean: continue
                
            entries = RAILWAY_TERMS_DICT.get(kw_clean)
            if entries:
                for entry in entries:
                    # 동음이의어 방지용 해시 (keyword+desc)
                    unique_hash = f"{kw_clean}_{entry['desc'][:20]}"
                    if unique_hash not in found_keys:
                        results.append({
                            "keyword": entry.get("category", "일반 용어"), # Frontend tag
                            "title": kw_clean,                           # Frontend subtitle
                            "desc": entry.get("desc", "")                 # Frontend text
                        })
                        found_keys.add(unique_hash)
        
        return results

def get_context_service() -> ContextProvider:
    """설정된 CONTEXT_PROVIDER 환경 변수에 따라 적절한 구현체를 반환하는 팩토리 함수"""
    provider_type = getattr(settings, "CONTEXT_PROVIDER", "mock").strip().lower()
    
    if provider_type == "mock":
        return MockContextProvider()
    elif provider_type == "csv":
        return CSVContextProvider()
    # elif provider_type == "rag":
    #     return RAGContextProvider()  # 향후 구축 시 연결
    else:
        logger.warning(f"[Context Service] 알 수 없는 프로바이더 '{provider_type}', Mock Provider로 폴백합니다.")
        return MockContextProvider()

# 전역 싱글톤 인스턴스 (워커에서 Import 용)
context_service = get_context_service()
