import requests
from abc import ABC
import logging
import json
import re
import pypinyin

logger = logging.getLogger(__name__)


def pinyin_to_camel(pinyin):
    """
    将拼音列表转换为驼峰命名
    例如: ['ni', 'hao', 'a'] -> 'NiHaoA'
    所有非字母数字字符会被替换为下划线
    """
    # 使用正则表达式将所有非字母数字字符（包括所有标点符号）替换为下划线
    cleaned = re.sub(r'[^\w\s]', '_', pinyin)
    # 将空格也替换为下划线
    cleaned = re.sub(r'\s+', '_', cleaned)
    # 移除连续的下划线并去除首尾下划线
    cleaned = re.sub(r'_+', '_', cleaned).strip('_')
    
    # 转换为拼音并生成驼峰命名
    pinyin_list = pypinyin.lazy_pinyin(cleaned)
    return "tool_" + "".join(word.capitalize() for word in pinyin_list)


class CompletionDifyAPI(ABC):
    def __init__(self, base_url: str, dify_app_sks: list, user="pp666"):
        # dify configs
        self.dify_base_url = base_url
        self.dify_app_sks = dify_app_sks
        self.user = user
        # dify app infos
        dify_app_infos = []
        dify_app_params = []
        dify_app_metas = []
        for key in self.dify_app_sks:
            dify_app_infos.append(self.get_app_info(key))
            dify_app_params.append(self.get_app_parameters(key))
            dify_app_metas.append(self.get_app_meta(key))

        self.dify_app_infos = dify_app_infos
        self.dify_app_params = dify_app_params
        self.dify_app_metas = dify_app_metas
        self.dify_app_names = [x["name"] for x in dify_app_infos]

    def chat_message(
        self,
        api_key,
        inputs={},
        response_mode="streaming",
        conversation_id=None,
        userId="pp666",
        files=None,
    ):
        url = f"{self.dify_base_url}/completion-messages"
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        }
        data = {
            "inputs": inputs,
            "response_mode": response_mode,
            "user": userId,
        }
        if conversation_id:
            data["conversation_id"] = conversation_id

        if response_mode == "streaming":
            response = requests.post(url, headers=headers, json=data, stream=True)

            # 处理流式响应
            full_answer = ""
            for line in response.iter_lines():
                if line:
                    # 跳过 "data:" 前缀
                    decoded_line = line.decode("utf-8")
                    if decoded_line.startswith("data:"):
                        try:
                            json_str = decoded_line[5:].strip()
                            data = json.loads(json_str)
                            if data.get("event") == "message" and "answer" in data:
                                # 累积完整答案
                                full_answer += data["answer"]
                                # 这里也可以选择处理每个部分响应，例如返回生成器
                                # yield data
                        except json.JSONDecodeError:
                            logger.warning(f"无法解析JSON数据: {decoded_line}")

            # 创建一个符合非流式响应格式的结果
            response_data = {"answer": full_answer}
            # 处理可能包含代码块的数据
            processed_data = self.process_answer_code_block(response_data)
            return processed_data
        else:
            response = requests.post(url, headers=headers, json=data)
            response_data = response.json()
            # 处理可能包含代码块的数据
            processed_data = self.process_answer_code_block(response_data)
            return processed_data

    def upload_file(self, api_key, file_path, user="pp666"):

        url = f"{self.dify_base_url}/files/upload"
        headers = {"Authorization": f"Bearer {api_key}"}
        files = {"file": open(file_path, "rb")}
        data = {"user": user}
        response = requests.post(url, headers=headers, files=files, data=data)
        response.raise_for_status()
        return response.json()

    def stop_response(self, api_key, task_id, user="pp666"):

        url = f"{self.dify_base_url}/chat-messages/{task_id}/stop"
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        }
        data = {"user": user}
        response = requests.post(url, headers=headers, json=data)
        response.raise_for_status()
        return response.json()

    def get_app_info(self, api_key, user="pp666"):

        url = f"{self.dify_base_url}/info"
        headers = {"Authorization": f"Bearer {api_key}"}
        # params = {"user": user}
        response = requests.get(url, headers=headers)
        response.raise_for_status()

        response_map = response.json()
        # 翻译工具名称
        from src.utils.tool_translation import TranslationService

        tool_name = response_map.get("name")
        if tool_name:
            # translated_name = TranslationService.translate_tool_name(tool_name)
            translated_name = pinyin_to_camel(tool_name)
            response_map["name"] = translated_name

        # 翻译工具描述
        # tool_description = response_map.get("description")
        # if tool_description:
        #     translated_description = TranslationService.translate_tool_description(
        #         tool_description
        #     )
        #     response_map["description"] = (
        #         f"{tool_description} ({translated_description})"
        #     )

        return response_map

    def get_app_parameters(self, api_key, user="pp666"):
        return {
            "user_input_form": [
                {"string": {"variable": "query", "label": "查询内容", "required": True}}
            ]
        }

    def get_app_meta(self, api_key, user="pp666"):
        url = f"{self.dify_base_url}/meta"
        headers = {"Authorization": f"Bearer {api_key}"}
        params = {"user": user}
        response = requests.get(url, headers=headers, params=params)
        response.raise_for_status()
        return response.json()

    @staticmethod
    def process_answer_code_block(data):
        try:
            # 获取answer字段
            answer = data.get("answer", "")

            # 构造符合workflow_finished格式的输出
            formatted_response = [
                {"event": "workflow_finished", "data": {"outputs": {"result": answer}}}
            ]

            # 尝试处理可能的代码块
            if answer.startswith("```") and answer.endswith("```"):
                try:
                    # 移除代码块标记并解析JSON
                    code_content = answer.strip("```").strip()
                    json_data = json.loads(code_content)

                    # 如果包含description字段，用它替换answer
                    if "description" in json_data:
                        formatted_response[0]["data"]["outputs"]["result"] = json_data[
                            "description"
                        ]
                except json.JSONDecodeError:
                    # 如果不是有效的JSON，保留原始代码块内容
                    pass

            return formatted_response
        except Exception as e:
            logger.warning(f"处理答案代码块时出错: {str(e)}")
            # 发生错误时返回符合格式的基础响应
            return [
                {
                    "event": "workflow_finished",
                    "data": {
                        "outputs": {
                            "error": str(e),
                            "fallback": data.get("answer", str(data)),
                        }
                    },
                }
            ]
