"""
统一的大模型服务接口

提供简化的API接口，方便现有代码迁移到新的架构
"""

from typing import List, Dict, Any, Optional, Union
from pathlib import Path
import PIL.Image
from loguru import logger

from .manager import LLMServiceManager
from .validators import OutputValidator
from .exceptions import LLMServiceError
from app.services.prompts import PromptManager

# 提供商注册由 webui.py:main() 显式调用（见 LLM 提供商注册机制重构）
# 这样更可靠，错误也更容易调试


class UnifiedLLMService:
    """统一的大模型服务接口"""
    
    @staticmethod
    async def analyze_images(images: List[Union[str, Path, PIL.Image.Image]],
                           prompt: str,
                           provider: Optional[str] = None,
                           batch_size: int = 10,
                           **kwargs) -> List[str]:
        """
        分析图片内容
        
        Args:
            images: 图片路径列表或PIL图片对象列表
            prompt: 分析提示词
            provider: 视觉模型提供商名称，如果不指定则使用配置中的默认值
            batch_size: 批处理大小
            **kwargs: 其他参数
            
        Returns:
            分析结果列表
            
        Raises:
            LLMServiceError: 服务调用失败时抛出
        """
        try:
            # 获取视觉模型提供商
            vision_provider = LLMServiceManager.get_vision_provider(provider)
            
            # 执行图片分析
            results = await vision_provider.analyze_images(
                images=images,
                prompt=prompt,
                batch_size=batch_size,
                **kwargs
            )
            
            logger.info(f"图片分析完成，共处理 {len(images)} 张图片，生成 {len(results)} 个结果")
            return results
            
        except Exception as e:
            logger.error(f"图片分析失败: {str(e)}")
            raise LLMServiceError(f"图片分析失败: {str(e)}")
    
    @staticmethod
    async def generate_text(prompt: str,
                          system_prompt: Optional[str] = None,
                          provider: Optional[str] = None,
                          temperature: float = 1.0,
                          max_tokens: Optional[int] = None,
                          response_format: Optional[str] = None,
                          **kwargs) -> str:
        """
        生成文本内容
        
        Args:
            prompt: 用户提示词
            system_prompt: 系统提示词
            provider: 文本模型提供商名称，如果不指定则使用配置中的默认值
            temperature: 生成温度
            max_tokens: 最大token数
            response_format: 响应格式 ('json' 或 None)
            **kwargs: 其他参数
            
        Returns:
            生成的文本内容
            
        Raises:
            LLMServiceError: 服务调用失败时抛出
        """
        try:
            # 获取文本模型提供商
            text_provider = LLMServiceManager.get_text_provider(provider)
            
            # 执行文本生成
            result = await text_provider.generate_text(
                prompt=prompt,
                system_prompt=system_prompt,
                temperature=temperature,
                max_tokens=max_tokens,
                response_format=response_format,
                **kwargs
            )
            
            logger.info(f"文本生成完成，生成内容长度: {len(result)} 字符")
            return result
            
        except Exception as e:
            logger.error(f"文本生成失败: {str(e)}")
            raise LLMServiceError(f"文本生成失败: {str(e)}")

    @staticmethod
    async def generate_text_stream(prompt: str,
                                 system_prompt: Optional[str] = None,
                                 provider: Optional[str] = None,
                                 temperature: float = 1.0,
                                 max_tokens: Optional[int] = None,
                                 response_format: Optional[str] = None,
                                 on_chunk=None,
                                 **kwargs) -> str:
        """
        流式生成文本内容；不支持流式的 provider 会退化为一次性返回。
        """
        try:
            text_provider = LLMServiceManager.get_text_provider(provider)
            result = await text_provider.generate_text_stream(
                prompt=prompt,
                system_prompt=system_prompt,
                temperature=temperature,
                max_tokens=max_tokens,
                response_format=response_format,
                on_chunk=on_chunk,
                **kwargs
            )

            logger.info(f"流式文本生成完成，生成内容长度: {len(result)} 字符")
            return result

        except Exception as e:
            logger.error(f"流式文本生成失败: {str(e)}")
            raise LLMServiceError(f"流式文本生成失败: {str(e)}")
    
    @staticmethod
    async def generate_narration_script(prompt: str,
                                      provider: Optional[str] = None,
                                      temperature: float = 1.0,
                                      validate_output: bool = True,
                                      **kwargs) -> List[Dict[str, Any]]:
        """
        生成解说文案
        
        Args:
            prompt: 提示词
            provider: 文本模型提供商名称
            temperature: 生成温度
            validate_output: 是否验证输出格式
            **kwargs: 其他参数
            
        Returns:
            解说文案列表
            
        Raises:
            LLMServiceError: 服务调用失败时抛出
        """
        try:
            # 生成文本
            result = await UnifiedLLMService.generate_text(
                prompt=prompt,
                provider=provider,
                temperature=temperature,
                response_format="json",
                **kwargs
            )
            
            # 验证输出格式
            if validate_output:
                narration_items = OutputValidator.validate_narration_script(result)
                logger.info(f"解说文案生成并验证完成，共 {len(narration_items)} 个片段")
                return narration_items
            else:
                # 简单的JSON解析
                import json
                parsed_result = json.loads(result)
                if "items" in parsed_result:
                    return parsed_result["items"]
                else:
                    return parsed_result
                    
        except Exception as e:
            logger.error(f"解说文案生成失败: {str(e)}")
            raise LLMServiceError(f"解说文案生成失败: {str(e)}")
    
    @staticmethod
    async def analyze_subtitle(subtitle_content: str,
                             provider: Optional[str] = None,
                             temperature: float = 1.0,
                             prompt_category: str = "short_drama_narration",
                             validate_output: bool = True,
                             **kwargs) -> str:
        """
        分析字幕内容
        
        Args:
            subtitle_content: 字幕内容
            provider: 文本模型提供商名称
            temperature: 生成温度
            validate_output: 是否验证输出格式
            **kwargs: 其他参数
            
        Returns:
            分析结果
            
        Raises:
            LLMServiceError: 服务调用失败时抛出
        """
        try:
            prompt = PromptManager.get_prompt(
                category=prompt_category,
                name="plot_analysis",
                parameters={"subtitle_content": subtitle_content},
            )
            prompt_object = PromptManager.get_prompt_object(
                category=prompt_category,
                name="plot_analysis",
            )
            system_prompt = prompt_object.get_system_prompt()
            
            # 生成分析结果
            result = await UnifiedLLMService.generate_text(
                prompt=prompt,
                system_prompt=system_prompt,
                provider=provider,
                temperature=temperature,
                **kwargs
            )
            
            # 验证输出格式
            if validate_output:
                validated_result = OutputValidator.validate_subtitle_analysis(result)
                logger.info("字幕分析完成并验证通过")
                return validated_result
            else:
                return result
                
        except Exception as e:
            logger.error(f"字幕分析失败: {str(e)}")
            raise LLMServiceError(f"字幕分析失败: {str(e)}")
    
    @staticmethod
    def get_provider_info() -> Dict[str, Any]:
        """
        获取所有提供商信息
        
        Returns:
            提供商信息字典
        """
        return LLMServiceManager.get_provider_info()
    
    @staticmethod
    def list_vision_providers() -> List[str]:
        """
        列出所有视觉模型提供商
        
        Returns:
            提供商名称列表
        """
        return LLMServiceManager.list_vision_providers()
    
    @staticmethod
    def list_text_providers() -> List[str]:
        """
        列出所有文本模型提供商
        
        Returns:
            提供商名称列表
        """
        return LLMServiceManager.list_text_providers()
    
    @staticmethod
    def clear_cache():
        """清空提供商实例缓存"""
        LLMServiceManager.clear_cache()
        logger.info("已清空大模型服务缓存")


# 为了向后兼容，提供一些便捷函数
async def analyze_images_unified(images: List[Union[str, Path, PIL.Image.Image]],
                               prompt: str,
                               provider: Optional[str] = None,
                               batch_size: int = 10) -> List[str]:
    """便捷的图片分析函数"""
    return await UnifiedLLMService.analyze_images(images, prompt, provider, batch_size)


async def generate_text_unified(prompt: str,
                              system_prompt: Optional[str] = None,
                              provider: Optional[str] = None,
                              temperature: float = 1.0,
                              response_format: Optional[str] = None) -> str:
    """便捷的文本生成函数"""
    return await UnifiedLLMService.generate_text(
        prompt, system_prompt, provider, temperature, response_format=response_format
    )
