"""Prompt 加载模块 - 从 YAML 文件加载 LLM prompts"""

import logging
from pathlib import Path
from typing import Optional

import yaml

logger = logging.getLogger(__name__)


class PromptLoader:
    """Prompt 加载器，支持从 YAML 文件加载 prompt"""

    _instance: Optional["PromptLoader"] = None
    _prompts: dict = {}

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._initialized = False
        return cls._instance

    def __init__(self):
        if self._initialized:
            return
        self._initialized = True
        self._prompts_dir = Path(__file__).parent.parent.parent.parent / "prompts"
        self._load_all_prompts()

    def _load_all_prompts(self):
        """递归加载所有 prompt YAML 文件"""
        if not self._prompts_dir.exists():
            logger.warning(f"Prompts directory not found: {self._prompts_dir}")
            return

        for yaml_file in self._prompts_dir.rglob("*.yaml"):
            self._load_prompt_file(yaml_file)

    def _load_prompt_file(self, file_path: Path):
        """加载单个 prompt YAML 文件"""
        try:
            with open(file_path, "r", encoding="utf-8") as f:
                data = yaml.safe_load(f)

            if not data:
                logger.warning(f"Empty prompt file: {file_path}")
                return

            name = data.get("name")
            if not name:
                logger.warning(f"Prompt file missing 'name': {file_path}")
                return

            self._prompts[name] = data
            logger.debug(f"Loaded prompt: {name} from {file_path}")

        except Exception as e:
            logger.error(f"Failed to load prompt file {file_path}: {e}")

    def get(self, name: str, default: Optional[str] = None, **kwargs) -> str:
        """获取 prompt 模板，支持变量替换

        Args:
            name: prompt 名称
            default: 如果不存在返回的默认值
            **kwargs: 模板变量

        Returns:
            替换后的 prompt 字符串
        """
        if name not in self._prompts:
            if default is not None:
                return default
            raise KeyError(f"Prompt '{name}' not found and no default provided")

        template = self._prompts[name].get("prompt", "")
        if not template:
            raise ValueError(f"Prompt '{name}' has no 'prompt' field")

        # 模板变量替换
        try:
            return template.format(**kwargs)
        except KeyError as e:
            raise KeyError(f"Missing template variable: {e}")

    def get_raw(self, name: str, default: Optional[str] = None) -> str:
        """获取原始 prompt 模板（不进行变量替换）"""
        if name not in self._prompts:
            return default
        return self._prompts[name].get("prompt", "")

    def exists(self, name: str) -> bool:
        """检查 prompt 是否存在"""
        return name in self._prompts

    def reload(self):
        """重新加载所有 prompts"""
        self._prompts.clear()
        self._load_all_prompts()


# 全局单例
_loader: Optional[PromptLoader] = None


def get_loader() -> PromptLoader:
    """获取全局 PromptLoader 实例"""
    global _loader
    if _loader is None:
        _loader = PromptLoader()
    return _loader
