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

logger = logging.getLogger(__name__)

import pypinyin


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 WorkflowDifyAPI(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}/workflows/run"
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        }
        data = {
            "inputs": inputs,
            "response_mode": response_mode,
            "user": userId,
        }
        logger.info("Sending data to Dify API: %s", data)
        logger.info("Sending headers to Dify API: %s", headers)
        logger.info("Sending url to Dify API: %s", url)
        if conversation_id:
            data["conversation_id"] = conversation_id
        if files:
            files_data = []
            for file_info in files:
                file_path = file_info.get("path")
                transfer_method = file_info.get("transfer_method")
                if transfer_method == "local_file":
                    files_data.append(("file", open(file_path, "rb")))
                elif transfer_method == "remote_url":
                    pass
            response = requests.post(
                url,
                headers=headers,
                data=data,
                files=files_data,
                stream=response_mode == "streaming",
            )
        else:
            response = requests.post(
                url, headers=headers, json=data, stream=response_mode == "streaming"
            )
        response.raise_for_status()
        if response_mode == "streaming":
            for line in response.iter_lines():
                if line:
                    if line.startswith(b"data:"):
                        try:
                            json_data = json.loads(line[5:].decode("utf-8"))
                            yield json_data
                        except json.JSONDecodeError:
                            print(f"Error decoding JSON: {line}")
        else:
            return response.json()

    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, params=params)
        response.raise_for_status()

        from src.utils.tool_translation import TranslationService

        response_map = response.json()

        # 翻译工具名称
        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"):
        url = f"{self.dify_base_url}/parameters"
        headers = {"Authorization": f"Bearer {api_key}"}
        params = {"user": user}
        response = requests.get(url, headers=headers, params=params)
        response.raise_for_status()
        return response.json()

    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()
