#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Prompt Manager
提示词管理器 - 动态加载和管理提示词模板
"""

import logging
from typing import Dict, Any, Optional, Tuple
from pathlib import Path
import os

from ..config import PromptConfig, ResourceConfig
from ..exceptions import ResourceNotFoundError

logger = logging.getLogger(__name__)


class PromptManager:
    """
    提示词管理器
    负责动态加载、缓存和管理提示词模板
    """

    def __init__(self, prompt_config: PromptConfig, resource_config: ResourceConfig):
        """
        初始化提示词管理器

        Args:
            prompt_config: 提示词配置
            resource_config: 资源配置
        """
        self.prompt_config = prompt_config
        self.resource_config = resource_config
        self._template_cache: Dict[str, str] = {}
        
        # 确定模板基础路径
        self.template_base_path = self._resolve_template_path()
        
        logger.info(f"提示词管理器初始化完成，模板路径: {self.template_base_path}")

    def _resolve_template_path(self) -> Optional[Path]:
        """解析提示词模板路径"""
        
        # 优先使用prompt_config中的路径
        if self.prompt_config.template_directory:
            template_path = Path(self.prompt_config.template_directory)
            if template_path.exists():
                return template_path
        
        # 使用resource_config的find_resource_directory方法
        resource_dir = self.resource_config.find_resource_directory("prompts")
        if resource_dir:
            return resource_dir
        
        # 如果还没找到，尝试resource_config中的路径
        if self.resource_config.prompt_template_directory:
            template_path = Path(self.resource_config.resolve_path(
                self.resource_config.prompt_template_directory
            ))
            if template_path.exists():
                return template_path
        
        # 扩展搜索路径，包括外部项目的常见路径
        search_paths = [
            # 内部模板路径
            Path("templates/prompts"),
            Path("travel_algorithms/templates/prompts"),
            
            # 外部项目路径
            Path("resource/prompt"),
            Path("../resource/prompt"),
            Path("../../resource/prompt"),
            Path("../../../resource/prompt"),
            
            # 相对于当前包的路径
            Path(__file__).parent.parent / "templates" / "prompts",
            
            # 工作目录相对路径
            Path.cwd() / "resource" / "prompt",
            Path.cwd().parent / "resource" / "prompt",
        ]
        
        for path in search_paths:
            try:
                if path.exists() and path.is_dir():
                    logger.info(f"找到提示词模板路径: {path.resolve()}")
                    return path.resolve()
            except Exception as e:
                logger.debug(f"检查路径失败 {path}: {e}")
                continue
        
        logger.warning("未找到提示词模板路径，将使用回退提示词")
        return None

    def get_prompt(self, task_type: str, prompt_type: str = "system") -> str:
        """
        获取提示词

        Args:
            task_type: 任务类型 (topic_generation, content_generation, etc.)
            prompt_type: 提示词类型 (system, user)

        Returns:
            提示词文本

        Raises:
            ResourceNotFoundError: 当提示词不存在且没有回退选项时
        """
        # 构建缓存键
        cache_key = f"{task_type}_{prompt_type}"
        
        # 检查缓存
        if cache_key in self._template_cache:
            return self._template_cache[cache_key]
        
        # 尝试从文件加载
        if self.prompt_config.enable_template_loading and self.template_base_path:
            try:
                prompt_text = self._load_from_file(task_type, prompt_type)
                if prompt_text:
                    self._template_cache[cache_key] = prompt_text
                    return prompt_text
            except Exception as e:
                logger.warning(f"从文件加载提示词失败 {cache_key}: {e}")
        
        # 使用回退提示词
        fallback_prompt = self._get_fallback_prompt(task_type, prompt_type)
        if fallback_prompt:
            self._template_cache[cache_key] = fallback_prompt
            return fallback_prompt
        
        # 如果都没有，抛出异常
        raise ResourceNotFoundError(f"未找到提示词: {task_type}.{prompt_type}")

    def _load_from_file(self, task_type: str, prompt_type: str) -> Optional[str]:
        """从文件加载提示词"""
        
        if not self.template_base_path:
            return None
        
        # 获取文件路径配置
        template_files = getattr(self.prompt_config, 'template_files', {})
        if task_type not in template_files:
            logger.debug(f"未配置任务类型 {task_type} 的模板文件")
            return None
        
        file_path_config = template_files[task_type].get(prompt_type)
        if not file_path_config:
            logger.debug(f"未配置 {task_type}.{prompt_type} 的模板文件")
            return None
        
        # 构建完整文件路径
        file_path = self.template_base_path / file_path_config
        
        if not file_path.exists():
            logger.warning(f"提示词文件不存在: {file_path}")
            return None
        
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read().strip()
            
            logger.debug(f"成功加载提示词文件: {file_path}")
            return content
            
        except Exception as e:
            logger.error(f"读取提示词文件失败 {file_path}: {e}")
            return None

    def _get_fallback_prompt(self, task_type: str, prompt_type: str) -> Optional[str]:
        """获取回退提示词"""
        
        fallback_prompts = getattr(self.prompt_config, 'fallback_prompts', {})
        
        if task_type in fallback_prompts:
            task_prompts = fallback_prompts[task_type]
            if isinstance(task_prompts, dict) and prompt_type in task_prompts:
                return task_prompts[prompt_type]
        
        return None

    def reload_templates(self) -> None:
        """重新加载所有模板（清除缓存）"""
        self._template_cache.clear()
        self.template_base_path = self._resolve_template_path()
        logger.info("提示词模板已重新加载")

    def get_available_templates(self) -> Dict[str, Dict[str, bool]]:
        """
        获取可用的模板列表

        Returns:
            任务类型 -> {prompt_type: 是否存在} 的字典
        """
        available = {}
        
        template_files = getattr(self.prompt_config, 'template_files', {})
        
        for task_type, file_configs in template_files.items():
            available[task_type] = {}
            
            for prompt_type, file_path_config in file_configs.items():
                if self.template_base_path:
                    file_path = self.template_base_path / file_path_config
                    available[task_type][prompt_type] = file_path.exists()
                else:
                    # 检查是否有回退提示词
                    fallback = self._get_fallback_prompt(task_type, prompt_type)
                    available[task_type][prompt_type] = fallback is not None
        
        return available

    def validate_templates(self) -> Dict[str, Any]:
        """
        验证所有模板的可用性

        Returns:
            验证结果字典
        """
        validation_result = {
            "template_base_path": str(self.template_base_path) if self.template_base_path else None,
            "template_base_exists": self.template_base_path.exists() if self.template_base_path else False,
            "templates": self.get_available_templates(),
            "missing_templates": [],
            "fallback_available": {}
        }
        
        # 检查缺失的模板
        template_files = getattr(self.prompt_config, 'template_files', {})
        for task_type, file_configs in template_files.items():
            for prompt_type in file_configs:
                if not validation_result["templates"].get(task_type, {}).get(prompt_type, False):
                    validation_result["missing_templates"].append(f"{task_type}.{prompt_type}")
                    
                    # 检查是否有回退选项
                    fallback = self._get_fallback_prompt(task_type, prompt_type)
                    validation_result["fallback_available"][f"{task_type}.{prompt_type}"] = fallback is not None
        
        return validation_result

    def format_prompt(self, prompt_template: str, **kwargs) -> str:
        """
        格式化提示词模板

        Args:
            prompt_template: 提示词模板
            **kwargs: 格式化参数

        Returns:
            格式化后的提示词
        """
        try:
            return prompt_template.format(**kwargs)
        except KeyError as e:
            logger.warning(f"提示词模板格式化缺少参数: {e}")
            return prompt_template
        except Exception as e:
            logger.error(f"提示词模板格式化失败: {e}")
            return prompt_template

    def get_prompt_with_format(self, task_type: str, prompt_type: str = "system", **kwargs) -> str:
        """
        获取并格式化提示词

        Args:
            task_type: 任务类型
            prompt_type: 提示词类型
            **kwargs: 格式化参数

        Returns:
            格式化后的提示词
        """
        template = self.get_prompt(task_type, prompt_type)
        return self.format_prompt(template, **kwargs) 