import requests
import json
import sys
import time
from np_log import setup_logging

logger = setup_logging('magic_api', console_level="info", file_level="error")
# logging = setup_logging('magic_api')

# 全局变量 - 基础URL
BASE_URL = 'http://192.168.31.125:9999'

class RequestClient():
    def __init__(self, base_url=BASE_URL, timeout=10, retries=3, retry_delay=2):
        self.base_url = base_url
        self.timeout = timeout
        self.retries = retries  # 最大重试次数
        self.retry_delay = retry_delay  # 每次重试间隔时间（秒）

    def post(self, endpoint, params=None, data=None, json=None, headers={'Content-Type': 'application/json'}):
        # 检查 endpoint 是否以 '/' 开头
        if not endpoint.startswith('/'):
            endpoint = f"/{endpoint}"
        url = f"{self.base_url}{endpoint}"
        # logger.info(f"Sending POST request to {url}")
        # logger.debug(f"Request data: {data}")
        # logger.debug(f"Request json: {json}")
        # logger.debug(f"Request headers: {headers}")

        for attempt in range(self.retries):
            try:
                response = requests.post(url, params=params,  data=data, json=json, headers=headers, timeout=self.timeout)
                response.raise_for_status()  # 如果状态码不是200，抛出HTTPError
                # logger.info(f"Response status code: {response.status_code}")
                # logger.debug(f"Response content: {response.text}")
                return response
            except requests.exceptions.RequestException as err:
                logger.error(f"Attempt {attempt + 1} failed: {err}")
                if attempt < self.retries - 1:
                    logger.info(f"Retrying in {self.retry_delay} seconds...")
                    time.sleep(self.retry_delay)
                else:
                    logger.error("All retries failed.")
                    raise  # 抛出最后的异常

    def get(self, endpoint, params=None, headers=None):
        # 检查 endpoint 是否以 '/' 开头
        if not endpoint.startswith('/'):
            endpoint = f"/{endpoint}"
        url = f"{self.base_url}{endpoint}"
        # logger.info(f"Sending GET request to {url}")
        # logger.debug(f"Request params: {params}")
        # logger.debug(f"Request headers: {headers}")

        for attempt in range(self.retries):
            try:
                response = requests.get(url, params=params, headers=headers, timeout=self.timeout)
                response.raise_for_status()  # 如果状态码不是200，抛出HTTPError
                # logger.info(f"Response status code: {response.status_code}")
                # logger.debug(f"Response content: {response.text}")
                return response
            # except requests.exceptions.RequestException as err:
            except Exception as err:
                logger.error(f"Attempt {attempt + 1} failed: {err}")
                if attempt < self.retries - 1:
                    logger.info(f"Retrying in {self.retry_delay} seconds...")
                    time.sleep(self.retry_delay)
                else:
                    logger.error("All retries failed.")
                    raise  # 抛出最后的异常

    def call_api(self, endpoint, method='get', params=None, json=None):
        """
        通用API调用函数
        :param endpoint: API端点
        :param method: 请求方法(get/post)
        :param params: 请求参数
        :param json_data: JSON数据
        :return: API响应或None
        """
        try:
            if method.lower() == 'get':
                # logger.info(f"GET请求: {endpoint}, {params}")
                response = self.get(endpoint, params=params)
            if method.lower() == 'post':
                # logger.info(f"POST请求: {endpoint}, {params}, {json}")
                response = self.post(endpoint, params=params, json=json)
                # logger.info(f"POST响应: {response.status_code}, {response.json()}")
            if response.status_code == 200:
                # data = response.json().get("data", "")
                return response.json().get("data", "")
            else:
                logger.error(f"API调用失败({endpoint}): {response.text}")
        except Exception as e:
            logger.error(f"API调用异常({endpoint}): {str(e)}, {sys.exc_info()}")
        return None

    # ========== monitor通用magic_api ==========
    def magic_api_select(self, data_base, tab_name, where_dict):
        """
        通用数据查询（支持动态条件数量）
        :param data_base: 数据库名
        :param tab_name: 表名
        :param where_dict: 动态关键字参数（字段=值 形式）
        :return: 查询结果 或 None
        """
        # print(f"magic_api_select:{data_base} {tab_name}, {where_dict}")
        # response = self.call_api(f"llm_select_tab_field_data/{data_base}/{tab_name}", params=where_dict)
        response = self.get(f"llm_select_tab_field_data/{data_base}/{tab_name}", params=where_dict)
        if response.json().get("message")== "success":
            return response.json().get("data", "")
        else:
            logger.error(f"查询失败: {tab_name} select {where_dict}, {response.json()}")

    def magic_api_update(self, data_base, tab_name, where_dict, set_dict):
        """
        更新数据状态（支持多字段更新和多条件）
        :param data_base: 数据库名
        :param tab_name: 表名
        :param where_dict: 条件字典 {条件字段: 条件值}
        :param set_dict: 要更新的字段字典 {字段名: 新值}
        :return: 无
        """

        # response = self.call_api(f"llm_update_tab_field_data/{tab_name}", method='post', params=where_dict, json=set_dict)
        response = self.post(f"llm_update_tab_field_data/{data_base}/{tab_name}", params=where_dict, json=set_dict)
        if response.json().get("message") == "success":
            set_dict = ", ".join([f"{k}={v}" for k, v in set_dict.items()])
            logger.debug(f"更新成功: {tab_name} update {set_dict} where {where_dict}, {response.json()}")
            # print(f"更新成功: {tab_name} update {set_dict} where {where_dict}, {response.json()}")
            return True
        else:
            logger.error(f"更新失败: {tab_name} update {set_dict} where {where_dict}, {response.json()}")
            return False

    def magic_api_insert(self, data_base, tab_name, set_dict):
        """
        插入数据状态（支持多字段更新和多条件）
        :param data_base: 数据库名
        :param tab_name: 表名
        :param set_dict: 要更新的字段字典 {字段名: 新值}
        :return: 无
        """

        # response = self.call_api(f"llm_insert_tab_field_data/{tab_name}", method='post', json=set_dict)
        response = self.post(f"llm_insert_tab_field_data/{data_base}/{tab_name}", json=set_dict)
        # print(response.json())
        if response.json().get("message")== "success":
            set_dict = ", ".join([f"{k}={v}" for k, v in set_dict.items()])
            logger.debug(f"插入成功: {tab_name} insert {set_dict}, {response.json()}")
        else:
            logger.error(f"插入失败: {tab_name} insert {set_dict}, {response.json()}")

    def select(self, data_base, tab_name, where_str, fields="*"):
        """
        通用数据查询（支持动态条件数量）
        :param data_base: 数据库名
        :param tab_name: 表名
        :param where_str: 动态关键字参数
        :param fields: 要查询的字段，默认为所有字段
        :return: 查询结果 或 None
        """
        sql = f"select {fields} from {data_base}.{tab_name} where {where_str}"
        response = self.get(f"select", params={"sql": sql})
        if response.json().get("message")== "success":
            return response.json().get("data", "")
        else:
            logger.error(f"查询失败: {tab_name} select {where_str}, {response.json()}")

    def update(self, data_base, tab_name, where_str: str, set_dict: dict):
        """
        更新数据状态（支持多字段更新和多条件）
        :param data_base: 数据库名
        :param tab_name: 表名
        :param set_str: 要更新的字段字符串
        :param where_str: 条件字符串
        :return: 无
        """
        if isinstance(where_str, dict):
            test = where_str
            where_str = set_dict
            set_dict = test

        set_dict = json.dumps(set_dict)
        set_dict = set_dict.replace(':', " =").replace("{", "").replace("}", "").replace('"', "")
        sql = f"update {data_base}.{tab_name} set {set_dict} where {where_str}"
        print(sql)
        response = self.post(f"update", params={"sql": sql})
        if response.json().get("message")== "success":
            logger.debug(f"更新成功: {tab_name} update {set_dict} where {where_str}, {response.json()}")
            return True
        else:
            logger.error(f"更新失败: {tab_name} update {set_dict} where {where_str}, {response.json()}")
            return False

    def insert(self, data_base, tab_name, set_str):
        """
        插入数据状态（支持多字段更新和多条件）
        :param data_base: 数据库名
        :param tab_name: 表名
        :param set_str: 要更新的字段字符串
        :return: 无
        """
        sql = f"insert into {data_base}.{tab_name} set {set_str}"
        response = self.post(f"insert", params={"sql": sql})
        if response.json().get("message")== "success":
            logger.debug(f"插入成功: {tab_name} insert {set_str}, {response.json()}")
            return True
        else:
            logger.error(f"插入失败: {tab_name} insert {set_str}, {response.json()}")
            return False

    # def magic_api_update_test(self, data_base, tab_name, set_dict, where_dict):
    #     """
    #     更新数据状态（支持多字段更新和多条件）
    #     :param tab_name: 表名
    #     :param set_dict: 要更新的字段字典 {字段名: 新值}
    #     :param where_dict: 条件字典 {条件字段: 条件值}
    #     :return: 无
    #     """
    #     set_dict = ", ".join([f"{k}={v}" for k, v in set_dict.items()])
    #     where_dict = " AND ".join([f"{k}={v}" for k, v in where_dict.items()])
    #     logger.info(f"状态更新成功: {tab_name} SET {set_dict} WHERE {where_dict}")

    def _init_error_body(self, init_info):
        """
        构建标准错误上报体，包含必填验证和默认值处理

        :param init_info: 字典包含以下字段:
            - 必填字段:
                device_name: 设备名 (e.g. AI服务器1, CRM服务器)
                name: 应用名称 (e.g. 本地大模型llm)
                task_type: 任务分类 (e.g. /api/generate)
                task_url: 任务地址 (e.g. 192.168.31.22_11434)
                person_name: 维护人 (e.g. 段文龙,刘金林)
            - 可选字段:
                error_info: 错误堆栈信息 (默认空字符串)
                task_id: 任务ID (默认None)
                trace_id: 调用链ID (默认None)
                update_info: 更新信息 (默认None)
                error_handling: 错误处理方式 (默认None)
                fault_tolerance: 容错方案 (默认None)
                module_name: 模块名 (默认"自动化")
        :return: 标准化错误上报字典
        """
        # 验证必填字段
        required_fields = [
            "device_name", "name", "task_type",
            "task_url", "person_name"
        ]
        for field in required_fields:
            if field not in init_info:
                raise KeyError(f"Missing required field: {field}")

        # 构建结构体，带默认值处理
        return {
            "device_name": init_info["device_name"],
            "error_info": init_info.get("error_info", ""),  # 默认为空
            "name": init_info["name"],
            "task_id": init_info.get("task_id"),
            "task_type": init_info["task_type"],
            "task_url": init_info["task_url"],
            "trace_id": init_info.get("trace_id"),
            "person_name": init_info["person_name"],
            "update_info": init_info.get("update_info"),
            "error_handling": init_info.get("error_handling"),
            "fault_tolerance": init_info.get("fault_tolerance"),
            "module_name": init_info.get("module_name", "自动化")  # 默认值
        }

    def get_error_body(self, init_info, error_info=None):
        """
        获取注入错误信息的报告体

        :param init_info: 基础信息字典
        :param error_info: 需要注入的错误堆栈
        :return: 完整错误报告体
        """
        body = self._init_error_body(init_info)
        if error_info:
            body["error_info"] = error_info
        return body

def magic_api(base_url = BASE_URL, endpoint=None, method='get', params=None, json_data=None):
    client = RequestClient(base_url)
    return client.call_api(endpoint, method, params=params, json=json_data)



MAGIC_BASE_URL = 'http://192.168.31.125:9999'
magic_client = RequestClient(MAGIC_BASE_URL)
init_info = {
    "device_name": "AI服务器1",
    "name": "本地大模型llm",
    "task_type": "/api/generate",
    "task_url": "192.168.31.22_11434",
    "person_name": "段文龙,刘金林",
    "error_info": "error_info",
    "task_id": "task_id",
    "trace_id": "trace_id",
    "update_info": "update_info",
    "error_handling": "error_handling",
    "fault_tolerance": "fault_tolerance",
    "module_name": "模块化"
}
body = magic_client.get_error_body(init_info, error_info=None)
# print(body)

body1 = magic_client.get_error_body(body, error_info='error_info')
logger.debug(f"magic_api配置: {body1}")
data = magic_api(endpoint="add_error_log", method="post", json_data=body)