import env  # 加载 .env 到环境变量
import requests
import json
import time
import logging
from typing import Optional, Dict, Any
import os

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class DeepSeekAPI:
    def __init__(self, api_key: Optional[str] = None):
        """
        初始化DeepSeek API客户端
        
        Args:
            api_key: DeepSeek API密钥，如果为None则从环境变量获取
        """
        self.api_key = api_key or os.getenv('DEEPSEEK_API_KEY')
        if not self.api_key:
            logger.warning("API密钥未提供且环境变量DEEPSEEK_API_KEY未设置")
        
        self.api_url = "https://api.deepseek.com/v1/chat/completions"
        self.max_retries = 3
        self.retry_delay = 2  # 秒
        
        # 默认系统提示词
        self.default_system_prompt = """你是一个专业的AI助手，能够准确理解用户需求并提供高质量的回答。
请根据用户的输入进行适当的处理和分析，保持回答的专业性和准确性。注意：所处理文字来自中央电视台新闻联播节目转文字，请在内容审查时重点考虑。"""

    def _handle_api_error(self, response: requests.Response) -> str:
        """
        处理API错误响应
        
        Args:
            response: API响应对象
            
        Returns:
            错误描述信息
        """
        error_msg = f"API请求失败: {response.status_code} {response.reason}"
        
        try:
            error_data = response.json()
            if 'error' in error_data:
                error_msg += f" - {error_data['error'].get('message', '未知错误')}"
                logger.error(f"API错误详情: {error_data}")
        except json.JSONDecodeError:
            error_msg += f" - 响应内容: {response.text[:200]}"
            
        return error_msg

    def _make_api_request(self, payload: Dict[str, Any]) -> Dict[str, Any]:
        """
        发送API请求并处理响应
        
        Args:
            payload: 请求数据
            
        Returns:
            API响应数据
            
        Raises:
            Exception: 当所有重试都失败时抛出异常
        """
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}"
        }
        
        last_exception = None
        
        for attempt in range(self.max_retries):
            try:
                logger.info(f"发送API请求 (尝试 {attempt + 1}/{self.max_retries})")
                
                response = requests.post(
                    self.api_url,
                    headers=headers,
                    json=payload,
                    timeout=60  # 60秒超时
                )
                
                if response.status_code == 200:
                    return response.json()
                elif response.status_code == 400:
                    # 400错误通常是请求格式问题，不需要重试
                    error_msg = self._handle_api_error(response)
                    raise Exception(f"请求参数错误: {error_msg}")
                elif response.status_code == 401:
                    # 401未授权错误，不需要重试
                    raise Exception("API密钥无效或未授权，请检查您的API密钥")
                elif response.status_code == 429:
                    # 速率限制，需要重试
                    logger.warning("达到速率限制，等待后重试...")
                    time.sleep(self.retry_delay * (attempt + 1))
                    continue
                elif 500 <= response.status_code < 600:
                    # 服务器错误，需要重试
                    logger.warning(f"服务器错误 {response.status_code}，等待后重试...")
                    time.sleep(self.retry_delay * (attempt + 1))
                    continue
                else:
                    error_msg = self._handle_api_error(response)
                    raise Exception(f"API请求失败: {error_msg}")
                    
            except requests.exceptions.Timeout:
                last_exception = Exception(f"请求超时 (尝试 {attempt + 1})")
                logger.warning(f"请求超时，等待后重试...")
                time.sleep(self.retry_delay * (attempt + 1))
                
            except requests.exceptions.ConnectionError:
                last_exception = Exception(f"网络连接错误 (尝试 {attempt + 1})")
                logger.warning(f"网络连接错误，等待后重试...")
                time.sleep(self.retry_delay * (attempt + 1))
                
            except requests.exceptions.RequestException as e:
                last_exception = Exception(f"请求异常: {str(e)}")
                logger.warning(f"请求异常，等待后重试...")
                time.sleep(self.retry_delay * (attempt + 1))
        
        # 所有重试都失败
        if last_exception:
            raise last_exception
        else:
            raise Exception("API请求失败，未知错误")

    def process_text(self,
                    prompt: str,
                    text: str,
                    system_prompt: Optional[str] = None,
                    model: str = "deepseek-chat",
                    temperature: float = 0.7,
                    max_tokens: int = 2000,
                    response_format: Optional[Dict] = None) -> str:
        """
        处理文本的通用方法
        
        Args:
            prompt: 用户提示词
            text: 需要处理的文本（约1万字符）
            system_prompt: 系统提示词，如果为None则使用默认值
            model: 使用的模型
            temperature: 生成温度
            max_tokens: 最大生成token数
            
        Returns:
            处理后的文本
            
        Raises:
            Exception: 当处理失败时抛出包含详细信息的异常
        """
        # 输入验证
        if not self.api_key:
            raise Exception("API密钥未设置，请提供api_key或设置DEEPSEEK_API_KEY环境变量")
        
        if not prompt or not text:
            raise Exception("prompt和text不能为空")
        
        # 检查文本长度（约1万字符）
        if len(text) > 15000:  # 留一些余量
            logger.warning(f"输入文本长度({len(text)}字符)较长，可能会超过上下文限制")
        
        # 准备系统提示词
        system_content = system_prompt or self.default_system_prompt
        
        # 构建消息
        messages = [
            {"role": "system", "content": system_content},
            {"role": "user", "content": f"{prompt}\n\n文本内容：\n{text}"}
        ]
        
        # 构建请求数据
        payload = {
            "model": model,
            "messages": messages,
            "temperature": temperature,
            "max_tokens": max_tokens,
            "stream": False
        }
        if response_format:
            payload["response_format"] = response_format
        
        try:
            # 发送API请求
            response_data = self._make_api_request(payload)
            
            # 解析响应
            if 'choices' in response_data and len(response_data['choices']) > 0:
                result = response_data['choices'][0]['message']['content']
                logger.info("文本处理成功完成")
                return result.strip()
            else:
                raise Exception("API响应格式异常，未找到有效结果")
                
        except Exception as e:
            logger.error(f"文本处理失败: {str(e)}")
            raise Exception(f"文本处理失败: {str(e)}")

    def process_text_with_fallback(self, 
                                 prompt: str, 
                                 text: str, 
                                 system_prompt: Optional[str] = None,
                                 **kwargs) -> str:
        """
        带降级处理的文本处理方法
        
        Args:
            prompt: 用户提示词
            text: 需要处理的文本
            system_prompt: 系统提示词
            **kwargs: 其他参数
            
        Returns:
            处理后的文本，如果API调用失败则返回降级结果
        """
        try:
            return self.process_text(prompt, text, system_prompt, **kwargs)
        except Exception as e:
            logger.error(f"API调用失败，使用降级处理: {str(e)}")
            # 这里可以添加降级逻辑，比如返回原始文本或简单处理
            return f"处理失败，返回原始文本（错误: {str(e)}）\n\n{text}"

# 使用示例
def deepseek_text(text, prompt):
    # 初始化API客户端
    # 方式1: 直接传入API密钥
    # api_client = DeepSeekAPI(api_key="your_deepseek_api_key_here")
    
    # 方式2: 从环境变量读取（推荐）
    api_client = DeepSeekAPI()  # API key 从环境变量 DEEPSEEK_API_KEY 读取
    
    # 示例文本（约1万字符）
    # sample_text = "这里是你的长文本内容..." * 500  # 模拟长文本
    
    # 自定义系统提示词（可选）
    custom_system_prompt = "你是一个专业的文本分析助手，擅长根据提示词对长文本进行深入分析。"
    
    try:
        # 处理文本（使用 response_format 强制返回 JSON）
        result = api_client.process_text(
            model=os.getenv('DEEPSEEK_MODEL', 'deepseek-chat'),
            prompt=prompt,
            text=text,
            system_prompt=custom_system_prompt,
            temperature=0.5,
            max_tokens=20000,
            response_format={"type": "json_object"}
        )
        
        #print("处理结果:")
        #print(result)
        return result
        
    except Exception as e:
        print(f"处理失败: {e}")
        
        # 使用降级方法
        fallback_result = api_client.process_text_with_fallback(
            prompt=prompt,
            text=text,
            system_prompt=custom_system_prompt
        )
        #print("降级处理结果:")
        #print(fallback_result)
        return result

if __name__ == "__main__":
    deepseek_text()