import logging
import requests
import json
import re
from core.providers.llm.base import LLMProviderBase

logger = logging.getLogger(__name__)

# 定义用于匹配中文标点符号的正则表达式（包括句号、感叹号、问号、分号）
punctuation_pattern = re.compile(r'([。！？；])')

class LLMProvider(LLMProviderBase):
    def __init__(self, config):
        self.personal_access_token = config.get("personal_access_token")
        self.bot_id = config.get("bot_id")
        self.user_id = config.get("user_id")  # 默认用户 ID
        self.base_url = config.get("base_url")

    def response(self, session_id, dialogue):
        try:
            # 从对话中取出最新的用户消息
            last_msg = next(m for m in reversed(dialogue) if m["role"] == "user")
            data = {
                "conversation_id": session_id,
                "bot_id": self.bot_id,
                "user": self.user_id,
                "query": last_msg["content"],
                "stream": True
            }
            logger.info(f"发送到 Coze API 的请求数据: {json.dumps(data, ensure_ascii=False)}")
            
            headers = {
                'Authorization': f'Bearer {self.personal_access_token}',
                'Content-Type': 'application/json',
                'Accept': '*/*',
                'Host': 'api.coze.cn',
                'Connection': 'keep-alive'
            }
            
            response = requests.post(
                self.base_url,
                headers=headers,
                json=data,
                stream=True
            )
            logger.info(f"请求状态: {response.status_code}")
            
            if response.status_code == 200:
                # 对每一行流数据进行处理，不做跨块累积
                for line_bytes in response.iter_lines(decode_unicode=False):
                    if not line_bytes:
                        continue
                    try:
                        # 使用 utf-8 解码，错误部分用替换符
                        line = line_bytes.decode('utf-8', errors='replace')
                    except Exception as e:
                        logger.error(f"解码失败: {e}")
                        continue
                    if line.startswith("data:"):
                        data_str = line[len("data:"):].strip()
                        if data_str == "[DONE]":
                            break
                        try:
                            data_chunk = json.loads(data_str)
                        except json.JSONDecodeError as e:
                            logger.error(f"JSON解析失败: {e} 数据: {line}")
                            continue
                        msg = data_chunk.get("message", {})
                        if msg.get("role") == "assistant" and msg.get("type") == "answer":
                            content = msg.get("content", "")
                            # 如果返回内容中包含标点符号，则按标点拆分，立即返回每个片段
                            if punctuation_pattern.search(content):
                                # 利用 finditer 找到每个标点，并返回以标点结尾的片段
                                start = 0
                                for match in punctuation_pattern.finditer(content):
                                    end = match.end()
                                    sentence = content[start:end].strip()
                                    if sentence:
                                        yield sentence
                                    start = end
                                # 如果拆分后剩余内容也返回（不含标点），直接返回
                                if start < len(content):
                                    remainder = content[start:].strip()
                                    if remainder:
                                        yield remainder
                            else:
                                # 如果没有标点，则直接返回这块内容
                                if content.strip():
                                    yield content.strip()
            else:
                logger.error(f"请求失败，状态码: {response.status_code}")
                yield f"【Coze服务响应异常：请求失败，状态码 {response.status_code}】"
        except Exception as e:
            logger.error(f"Error in Coze response generation: {e}")
            yield "【Coze服务响应异常】"
