"""
Dashscope模型调用封装模块
提供统一的模型调用接口，支持重试机制和错误处理
"""

import os
import time
from dotenv import load_dotenv
import dashscope
from http import HTTPStatus
from config import MODEL_CONFIG, get_api_key

# 加载环境变量并设置API Key
load_dotenv()
dashscope.api_key = get_api_key()


class DashscopeModel:
    """
    Dashscope模型调用封装类
    
    功能：
    1. 封装Dashscope SDK的调用细节
    2. 提供自动重试机制
    3. 统一的返回格式
    4. 错误处理和日志记录
    """
    
    def __init__(self, model_name=None, temperature=None):
        """
        初始化模型客户端
        
        Args:
            model_name: 模型名称，默认从配置读取
            temperature: 温度参数，默认从配置读取
        """
        self.model_name = model_name or MODEL_CONFIG["model_name"]
        self.temperature = temperature if temperature is not None else MODEL_CONFIG["temperature"]
        self.max_retries = MODEL_CONFIG["max_retries"]
        self.timeout = MODEL_CONFIG["timeout"]
        
    def call(self, prompt, retry_count=0):
        """
        调用模型并返回结果
        
        Args:
            prompt: 输入的提示词
            retry_count: 当前重试次数（内部使用）
            
        Returns:
            dict: 包含以下字段的字典
                - success: 是否成功
                - content: 模型输出的文本内容（成功时）
                - tokens: 消耗的token总数（成功时）
                - error: 错误信息（失败时）
        """
        try:
            # 调用Dashscope API
            response = dashscope.Generation.call(
                model=self.model_name,
                messages=[{"role": "user", "content": prompt}],
                temperature=self.temperature,
                result_format="message"
            )
            
            # 检查响应状态
            if response.status_code == HTTPStatus.OK:
                # 提取输出内容
                content = response.output.choices[0].message.content
                tokens = response.usage.total_tokens if hasattr(response, 'usage') else 0
                
                return {
                    "success": True,
                    "content": content,
                    "tokens": tokens
                }
            else:
                # API返回错误，尝试重试
                error_msg = f"API错误: {response.code} - {response.message}"
                if retry_count < self.max_retries:
                    print(f"  ⚠️ 调用失败，{retry_count + 1}/{self.max_retries}次重试...")
                    time.sleep(1)  # 等待1秒后重试
                    return self.call(prompt, retry_count + 1)
                
                return {
                    "success": False,
                    "error": error_msg
                }
                
        except Exception as e:
            # 发生异常，尝试重试
            error_msg = f"调用异常: {str(e)}"
            if retry_count < self.max_retries:
                print(f"  ⚠️ 发生异常，{retry_count + 1}/{self.max_retries}次重试...")
                time.sleep(1)
                return self.call(prompt, retry_count + 1)
            
            return {
                "success": False,
                "error": error_msg
            }
    
    def call_with_retry(self, prompt):
        """
        带重试机制的模型调用（call的别名，保持向后兼容）
        
        Args:
            prompt: 输入的提示词
            
        Returns:
            dict: 调用结果
        """
        return self.call(prompt)


class MockModel:
    """
    模拟模型（用于测试，不消耗API额度）
    """
    
    def __init__(self, model_name="mock-model", temperature=0.1):
        self.model_name = model_name
        self.temperature = temperature
        
    def call(self, prompt):
        """模拟调用，返回预设的测试数据"""
        import random
        
        # 模拟不同的响应
        responses = [
            "这是一个模拟的回答。在实际运行中，这里会显示模型的真实输出。",
            "模拟思维链输出：\n1. 首先分析问题...\n2. 然后逐步推理...\n3. 最终得出结论...\n\n最终答案：示例答案",
            "根据提示词的要求，我进行了详细的思考...\n\n最终答案是：42"
        ]
        
        return {
            "success": True,
            "content": random.choice(responses),
            "tokens": random.randint(50, 200)
        }


# 便捷函数：快速创建模型实例
def create_model(use_mock=False, **kwargs):
    """
    创建模型实例的工厂函数
    
    Args:
        use_mock: 是否使用模拟模型（测试用）
        **kwargs: 传递给模型构造函数的参数
        
    Returns:
        DashscopeModel 或 MockModel 实例
    """
    if use_mock:
        return MockModel(**kwargs)
    return DashscopeModel(**kwargs)
