"""
设备操作模块

该模块提供了设备操作的接口，用于控制不同位置的各种设备。
"""

import os
import requests
import json
from typing import Dict, Any, Optional, List
from ..config import CONFIG
from .device_results_pretreatment import process_device_data, process_device_results
from .logger_config import get_logger

# 延迟初始化日志器，避免在导入时立即执行
logger = None

def _ensure_logger():
    """确保日志器已初始化"""
    global logger
    if logger is None:
        logger = get_logger(__name__)
    return logger

enterprise_id = os.environ.get("enterpriseId", CONFIG["enterprise_id"])


class DeviceOperator:
    """设备操作类，提供设备控制功能"""

    def __init__(self, api_base_url: str = None):
        """
        初始化设备操作器

        参数:
            api_base_url: API服务的基础URL
        """
        logger = _ensure_logger()
        self.api_base_url = api_base_url or CONFIG["device_api_base_url"]
        self.session = requests.Session()
        # 设置默认超时
        self.session.timeout = CONFIG["request_timeout"]

        logger.info(f"DeviceOperator初始化完成，API基础URL: {self.api_base_url}")

    def set_enterprise_id_to_env(self, enterprise_id_value: str) -> None:
        """
        将企业ID存入环境变量

        参数:
            enterprise_id_value: 企业ID值
        """
        logger = _ensure_logger()
        if not enterprise_id_value or not isinstance(enterprise_id_value, str):
            logger.warning(f"无效的企业ID值: {enterprise_id_value}")
            return

        os.environ["enterpriseId"] = enterprise_id_value
        global enterprise_id
        enterprise_id = enterprise_id_value
        logger.info(f"企业ID已更新: {enterprise_id_value}")

    def get_enterprise_id_by_user(self, user_id: str) -> Optional[str]:
        """
        根据用户ID获取企业ID并存入环境变量

        参数:
            user_id: 用户ID

        返回:
            Optional[str]: 企业ID，获取失败时返回None
        """
        logger = _ensure_logger()
        if not user_id or not isinstance(user_id, str):
            logger.error(f"无效的用户ID: {user_id}")
            return None

        # 调用实际API获取企业ID
        url = f"{self.api_base_url}/system/enterprise/user/{user_id}"
        headers = {
            "Accept": "*/*",
        }

        try:
            logger.info(f"正在获取用户 {user_id} 的企业ID...")
            response = self.session.get(
                url=url, headers=headers, timeout=CONFIG["request_timeout"]
            )

            if response.status_code == 200:
                data = response.json()
                if (
                    data.get("code") == 200
                    and data.get("data")
                    and data["data"].get("id")
                ):
                    enterprise_id_value = str(data["data"]["id"])
                    # 将企业ID存入环境变量
                    self.set_enterprise_id_to_env(enterprise_id_value)
                    logger.info(f"成功获取企业ID: {enterprise_id_value}")
                    return enterprise_id_value
                else:
                    logger.warning(f"API返回数据格式异常: {data}")
            else:
                logger.error(
                    f"API请求失败，状态码: {response.status_code}, 响应: {response.text}"
                )

            # 如果API调用失败或数据格式不符预期，返回默认值
            logger.info(f"使用默认企业ID: {enterprise_id}")
            return enterprise_id

        except requests.exceptions.Timeout:
            logger.error(f"获取企业ID请求超时，用户ID: {user_id}")
            return enterprise_id
        except requests.exceptions.RequestException as e:
            logger.error(f"获取企业ID网络请求异常: {str(e)}")
            return enterprise_id
        except Exception as e:
            logger.error(f"获取企业ID时发生未知异常: {str(e)}", exc_info=True)
            return enterprise_id

    # 设备结果分数判断
    def check_device_results_score(
        self, best_match_data: Optional[Dict[str, Any]]
    ) -> Dict[str, Any]:
        """
        检查设备匹配的准确性

        根据你的代码分析，评分系统说明:
        - 综合分数(combined_score)或score是最终评判标准
        - 0.85-0.88: 准确匹配，可信度高 (随机阈值)
        - 0.7-0.84: 一般匹配，需要确认
        - 0.5-0.69: 较差匹配，不建议使用
        - <0.5: 很差匹配，不推荐

        Args:
            best_match_data: best_match数据，包含device和score信息

        Returns:
            Dict: {
                "checkResult": True/False,  # 是否满足分数要求(随机阈值0.85-0.88)
                "data": data                # 满足要求返回对应项，不满足返回整个data
            }
        """
        logger.debug("开始检查设备匹配准确性...")
        
        import random

        # 提取分数 - 优先使用combined_score，其次使用score
        score = best_match_data.get("combined_score", best_match_data.get("score", 0.0))
        logger.debug(f"提取的匹配分数: {score}")

        # 生成随机阈值 (0.85-0.88之间)
        random_threshold = round(random.uniform(0.6, 0.65), 2)
        logger.debug(f"生成的随机阈值: {random_threshold}")

        # 判断是否满足准确性要求 (随机阈值-1.0)
        is_accurate = random_threshold <= score <= 1.0
        
        logger.info(f"设备匹配准确性检查: 分数={score}, 阈值={random_threshold}, 通过={is_accurate}")

        # 构造返回结果
        result = {"checkResult": is_accurate, "data": best_match_data}
        return result

    def preprocess_results(self, raw_data: List[List[Any]]) -> List[Dict[str, Any]]:
        """
        预处理数据，将原始数据转换为简化的数组对象格式
        如果 entityId 相同，则合并到一起

        Args:
            raw_data: 原始数据，格式为 [[entity, score], ...]

        Returns:
            处理后的数据数组，每个对象包含合并后的信息（不包含id和score_details字段）
        """
        logger.debug(f"开始预处理设备结果数据，原始数据条数: {len(raw_data) if raw_data else 0}")
        
        try:
            result = process_device_results(raw_data)
            logger.info(f"设备结果数据预处理完成，输出条数: {len(result) if result else 0}")
            return result
        except Exception as e:
            logger.error(f"预处理设备结果数据时发生异常: {str(e)}", exc_info=True)
            return []

    def preprocess_parameters(
        self,
        data: Optional[Dict[str, Any]],
    ) -> Dict[str, Any]:
        """
        预处理设备操作参数，使用process_device_data方法处理数据

        参数:
            data: 需要预处理的数据，包含best_match信息
                格式如：{
                    "best_match": {
                        "device": {
                            "device": {
                                "key": "switch.zimi_cn_1144138206_dhkg01_on_p_2_1",
                                "description": "灵泽办公区过道吊灯  开关 按键"
                            },
                            "operation": {
                                "key": "turn_on",
                                "description": "开关"
                            }
                        }
                    }
                }

        返回:
            Dict[str, Any]: 预处理后的设备操作参数
                格式如：{
                    "enterpriseId": "1932095424144715777",
                    "entityId": "switch.zimi_cn_1144138206_dhkg01_on_p_2_1",
                    "command": "turn_on"
                }
        """
        # 默认结果结构
        default_result = {"enterpriseId": enterprise_id, "entityId": "", "command": ""}

        try:
            # 使用process_device_data方法处理数据
            if data and isinstance(data, dict):
                processed_result = process_device_data(data, enterprise_id)
                if processed_result:
                    logger.info(f"成功处理设备数据: {processed_result}")
                    return processed_result
                else:
                    logger.warning("process_device_data返回None，使用默认结果")
            else:
                logger.warning("输入数据为空或格式异常")

        except Exception as e:
            logger.error(f"预处理参数时发生异常: {str(e)}", exc_info=True)

        return default_result

    def operate_device(self, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """
        操作设备的方法

        参数:
            data: 设备操作数据，包含entityId、command等信息

        返回:
            Dict[str, Any]: 包含操作结果的字典
        """
        # 初始化操作参数
        if data is None:
            data = {}

        # 检查并设置 enterpriseId
        if not data.get("enterpriseId"):
            data["enterpriseId"] = enterprise_id
            logger.info(f"data中未包含enterpriseId，使用默认值: {enterprise_id}")

        # 验证必要参数
        if not data.get("entityId") or not data.get("command"):
            error_msg = "缺少必要的设备操作参数: entityId 和 command"
            logger.error(error_msg)
            return {"code": 400, "msg": error_msg, "data": None}

        logger.info(
            f"开始操作设备 - entityId: {data.get('entityId')}, command: {data.get('command')}"
        )
        #     # 保存map_result到本地JSON文件
        # output_file_path = r"E:\yh-ai\project\lzwcai-szyg\lzwcai-mcp-server-package\lzwcai_mcp_iot\output\data.json"
        # with open(output_file_path, "w", encoding="utf-8") as f:
        #     json.dump(data, f, ensure_ascii=False, indent=2)
        # logger.info(f"map_result已保存到: {output_file_path}")

        # 调用API接口
        result = self.call_device_api(data)
        # result =  {"code": 200, "msg": "操作成功", "data": None}
        return result

    def batch_operate_devices(self, devices_data: List[Dict[str, Any]]) -> Dict[str, Any]:
        """
        批量操作设备的方法

        参数:
            devices_data: 设备操作数据数组，每个元素包含entityId、command等信息
                         数据结构与operate_device方法的data参数相同

        返回:
            Dict[str, Any]: 批量操作结果，包含成功/失败统计和详细结果
                {
                    "code": 200,  # 整体状态码
                    "msg": "批量操作完成",
                    "data": {
                        "total": 总数量,
                        "success": 成功数量,
                        "failed": 失败数量,
                        "results": [
                            {
                                "index": 索引,
                                "deviceInfo": 设备信息,
                                "result": 操作结果,
                                "success": True/False
                            }
                        ]
                    }
                }
        """
        if not devices_data or not isinstance(devices_data, list):
            error_msg = "无效的设备数据：devices_data必须是一个非空数组"
            logger.error(error_msg)
            return {"code": 400, "msg": error_msg, "data": None}

        total_count = len(devices_data)
        success_count = 0
        failed_count = 0
        results = []

        logger.info(f"开始批量操作设备，总数量: {total_count}")

        for index, device_data in enumerate(devices_data):
            device_info = { **device_data,"index": index}

            try:
                logger.info(f"正在操作第 {index + 1}/{total_count} 个设备: {device_info['entityId']}")
                
                # 验证设备数据格式
                if not isinstance(device_data, dict):
                    raise ValueError(f"设备数据格式错误，必须是字典类型")

                # 调用单个设备操作方法
                operation_result = self.operate_device(device_data)
                
                # 判断操作是否成功（通常code=200表示成功）
                is_success = operation_result.get("code") == 200
                
                if is_success:
                    success_count += 1
                    logger.info(f"设备操作成功: {device_info['entityId']}")
                else:
                    failed_count += 1
                    logger.warning(f"设备操作失败: {device_info['entityId']}, 原因: {operation_result.get('msg', '未知错误')}")

                # 记录结果
                results.append({
                    "index": index,
                    "deviceInfo": device_info,
                    "result": operation_result,
                    "success": is_success
                })

            except Exception as e:
                failed_count += 1
                error_msg = f"设备操作异常: {str(e)}"
                logger.error(f"第 {index + 1} 个设备操作异常: {error_msg}", exc_info=True)
                
                # 记录异常结果
                results.append({
                    "index": index,
                    "deviceInfo": device_info,
                    "result": {"code": 500, "msg": error_msg, "data": None},
                    "success": False
                })

        # 构建返回结果
        summary_msg = f"批量操作完成，总数: {total_count}, 成功: {success_count}, 失败: {failed_count}"
        logger.info(summary_msg)

        # 整体状态码判断：如果全部成功则返回200，部分成功返回206，全部失败返回500
        if success_count == total_count:
            overall_code = 200
            overall_msg = "批量操作全部成功"
        elif success_count > 0:
            overall_code = 206  # 部分成功
            overall_msg = f"批量操作部分成功，成功: {success_count}, 失败: {failed_count}"
        else:
            overall_code = 500
            overall_msg = "批量操作全部失败"

        return {
            "code": overall_code,
            "msg": overall_msg,
            "data": {
                "total": total_count,
                "success": success_count,
                "failed": failed_count,
                "success_rate": round(success_count / total_count * 100, 2) if total_count > 0 else 0,
                "results": results
            }
        }

    def get_digital_employee_by_id(self, employee_id: str) -> Dict[str, Any]:
        """
        根据员工ID获取数字员工信息

        参数:
            employee_id: 员工ID

        返回:
            Dict[str, Any]: 包含数字员工信息的字典
        """
        if not employee_id or not isinstance(employee_id, str):
            error_msg = f"无效的员工ID: {employee_id}"
            logger.error(error_msg)
            return {"code": 400, "msg": error_msg, "data": None}

        # API配置
        url = f"{self.api_base_url}/system/mcpServer/getByEmployeeId/{employee_id}"
        headers = {}

        try:
            logger.info(f"正在获取员工ID为 {employee_id} 的数字员工信息...")
            response = self.session.get(
                url=url, headers=headers, timeout=CONFIG["request_timeout"]
            )

            # 处理响应
            if response.status_code == 200:
                data = response.json()
                logger.info(f"成功获取数字员工信息: {data}")
                return data
            else:
                error_msg = f"API请求失败，状态码: {response.status_code}, 响应: {response.text}"
                logger.error(error_msg)
                return {
                    "code": response.status_code,
                    "msg": error_msg,
                    "data": None,
                }

        except requests.exceptions.Timeout:
            error_msg = f"获取数字员工信息请求超时，员工ID: {employee_id}"
            logger.error(error_msg)
            return {"code": 408, "msg": error_msg, "data": None}
        except requests.exceptions.RequestException as e:
            error_msg = f"获取数字员工信息网络请求异常: {str(e)}"
            logger.error(error_msg)
            return {"code": 500, "msg": error_msg, "data": None}
        except Exception as e:
            error_msg = f"获取数字员工信息时发生未知异常: {str(e)}"
            logger.error(error_msg, exc_info=True)
            return {"code": 500, "msg": error_msg, "data": None}

    def get_user_spaces_by_user_id(self, user_id: str) -> Dict[str, Any]:
        """
        根据用户ID获取该用户关联的空间信息

        参数:
            user_id: 用户ID

        返回:
            Dict[str, Any]: 接口响应结果，结构为 {"code": number, "msg": string, "data": any}
        """
        if not user_id or not isinstance(user_id, str):
            error_msg = f"无效的用户ID: {user_id}"
            logger.error(error_msg)
            return {"code": 400, "msg": error_msg, "data": None}

        url = f"{self.api_base_url}/system/mcpServer/space/user/{user_id}"
        headers = {
            "Accept": "*/*",
        }

        try:
            logger.info(f"正在获取用户ID为 {user_id} 的空间信息...")
            response = self.session.get(
                url=url, headers=headers, timeout=CONFIG["request_timeout"]
            )

            if response.status_code == 200:
                try:
                    data = response.json()
                except ValueError:
                    data = {}

                if isinstance(data, dict):
                    # 统一返回格式，确保存在 code/msg/data 字段
                    if "code" not in data:
                        data["code"] = 200
                    if "msg" not in data:
                        data["msg"] = "success"
                    # 接口可能没有返回 data 时，显式置为 None
                    if "data" not in data or data["data"] in (None, [], {}):
                        data["data"] = None
                    logger.info(f"成功获取用户空间信息: {data}")
                    return data
                else:
                    wrapped = {"code": 200, "msg": "success", "data": None}
                    logger.info(f"成功获取用户空间信息(非字典响应已包装): {wrapped}")
                    return wrapped
            else:
                error_msg = f"API请求失败，状态码: {response.status_code}, 响应: {response.text}"
                logger.error(error_msg)
                return {
                    "code": response.status_code,
                    "msg": error_msg,
                    "data": None,
                }

        except requests.exceptions.Timeout:
            error_msg = f"获取用户空间信息请求超时，用户ID: {user_id}"
            logger.error(error_msg)
            return {"code": 408, "msg": error_msg, "data": None}
        except requests.exceptions.RequestException as e:
            error_msg = f"获取用户空间信息网络请求异常: {str(e)}"
            logger.error(error_msg)
            return {"code": 500, "msg": error_msg, "data": None}
        except Exception as e:
            error_msg = f"获取用户空间信息时发生未知异常: {str(e)}"
            logger.error(error_msg, exc_info=True)
            return {"code": 500, "msg": error_msg, "data": None}

    def call_device_api(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """
        调用设备操作API

        参数:
            data: 设备操作数据，包含entityId、command等信息

        返回:
            Dict[str, Any]: API调用结果
        """
        # API配置
        url = f"{self.api_base_url}/space_iot/operation/call"
        headers = {
            "Content-Type": "application/json",
        }

        # 构建请求数据
        request_data = {**data}

        try:
            logger.info(f"调用设备操作API: {url}")
            logger.debug(f"请求数据: {request_data}")

            # 发送POST请求
            response = self.session.post(
                url=url,
                headers=headers,
                data=json.dumps(request_data),
                timeout=CONFIG["request_timeout"],
            )

            # 处理响应
            if response.status_code == 200:
                result = response.json()
                logger.info(f"设备操作API调用成功: {result}")
                return result
            else:
                error_msg = f"API请求失败，状态码: {response.status_code}, 响应: {response.text}"
                logger.error(error_msg)
                return {
                    "code": response.status_code,
                    "msg": error_msg,
                    "data": None,
                }

        except requests.exceptions.Timeout:
            error_msg = "设备操作API请求超时"
            logger.error(error_msg)
            return {"code": 408, "msg": error_msg, "data": None}
        except requests.exceptions.RequestException as e:
            error_msg = f"设备操作API网络请求异常: {str(e)}"
            logger.error(error_msg)
            return {"code": 500, "msg": error_msg, "data": None}
        except Exception as e:
            error_msg = f"设备操作API调用异常: {str(e)}"
            logger.error(error_msg, exc_info=True)
            return {"code": 500, "msg": error_msg, "data": None}


    def get_operation_analysis_result(self, tool_data: Dict[str, Any], best_match: Optional[Dict[str, Any]]) -> str:
        """
        分析操作结果，根据 tool_data 和 best_match 返回合适的操作命令
        
        参数:
            tool_data: 工具数据，包含 location、device、operation、keyId
            best_match: 最佳匹配结果，包含设备信息和评分
            
        返回:
            str: 操作命令字符串
        """
        logger.debug("开始分析操作结果...")
        logger.debug(f"输入参数 - tool_data: {tool_data}, best_match: {best_match}")
        
        def contains_chinese(text: str) -> bool:
            """检查字符串是否包含中文字符"""
            if not text:
                return False
            for char in text:
                if '\u4e00' <= char <= '\u9fff':
                    return True
            return False
        
        try:
            # 获取 tool_data 中的 operation
            tool_operation = tool_data.get("operation", "") if tool_data else ""
            logger.debug(f"tool_data 中的 operation: {tool_operation}")
            
            # 判断 tool_data 的 operation 是否是纯英文（不包含中文）
            if tool_operation and not contains_chinese(tool_operation):
                logger.info(f"tool_data operation 为纯英文，直接使用: {tool_operation}")
                return tool_operation
            
            # 如果 tool_data 的 operation 包含中文或为空，检查 best_match
            logger.debug("tool_data operation 包含中文或为空，尝试使用 best_match")
            if best_match and isinstance(best_match, dict):
                device_info = best_match.get("device", {})
                if device_info and isinstance(device_info, dict):
                    operation_info = device_info.get("operation", {})
                    if operation_info and isinstance(operation_info, dict):
                        operation_key = operation_info.get("key", "")
                        if operation_key:
                            logger.info(f"从 best_match 获取到操作命令: {operation_key}")
                            return operation_key
            
            # 如果都没有有效值，返回原始的 tool_operation 或空字符串
            logger.warning(f"未找到有效的操作命令，返回原始值: {tool_operation}")
            return tool_operation or ""
            
        except Exception as e:
            logger.error(f"分析操作结果时发生异常: {str(e)}", exc_info=True)
            return ""

    def __del__(self):
        """析构函数，关闭会话"""
        if hasattr(self, "session"):
            self.session.close()


# 使用示例
if __name__ == "__main__":
    # 测试代码只在直接运行此模块时执行，不在导入时执行
    # 以下代码已注释避免MCP服务器启动时执行
    pass
    
    # device_op = DeviceOperator()

    # # 测试获取数字员工信息
    # employee_id = "1950037223825125378"
    # employee_result = device_op.get_digital_employee_by_id(employee_id)
    # logger.info(f"数字员工信息: {employee_result}")

    # 以下所有测试代码已注释，避免MCP服务器启动时执行
    
    # device_op = DeviceOperator()

    # # 测试获取数字员工信息
    # employee_id = "1950037223825125378"
    # employee_result = device_op.get_digital_employee_by_id(employee_id)
    # logger.info(f"数字员工信息: {employee_result}")

    # # 测试单个设备操作
    # data = {
    #     "enterpriseId": "1932095424144715777",
    #     "entityId": "climate.qjiang_cn_741479129_wb20",
    #     "command": "set_temperature",
    #     "params": {
    #         "temperature": 24,
    #     },
    # }
    # result = device_op.operate_device(data)
    # logger.info(f"设备操作结果: {result}")

    # # 测试批量设备操作
    # batch_data = [
    #     {
    #         "enterpriseId": "1932095424144715777",
    #         "entityId": "switch.office_light_1",
    #         "command": "turn_on",
    #         "params": {}
    #     },
    #     {
    #         "enterpriseId": "1932095424144715777",
    #         "entityId": "climate.office_ac_1",
    #         "command": "set_temperature",
    #         "params": {
    #             "temperature": 25,
    #         }
    #     },
    #     {
    #         "enterpriseId": "1932095424144715777",
    #         "entityId": "switch.meeting_room_projector",
    #         "command": "turn_off",
    #         "params": {}
    #     }
    # ]
    
    # batch_result = device_op.batch_operate_devices(batch_data)
    # logger.info(f"批量设备操作结果: {batch_result}")
    
    # # 输出批量操作统计信息
    # if batch_result.get("code") in [200, 206]:  # 成功或部分成功
    #     batch_data_result = batch_result.get("data", {})
    #     logger.info(f"批量操作统计: 总数={batch_data_result.get('total')}, "
    #                  f"成功={batch_data_result.get('success')}, "
    #                  f"失败={batch_data_result.get('failed')}, "
    #                  f"成功率={batch_data_result.get('success_rate')}%")
    
    # # 测试操作分析结果方法
    # # 测试用例1：tool_data 包含纯英文操作
    # tool_data_en = {
    #     "location": "office",
    #     "device": "air_conditioner", 
    #     "operation": "turn_on",
    #     "keyId": "1932095424144715777"
    # }
    
    # best_match_data = {
    #     "device": {
    #         "id": "d67d81ef-1c0e-4049-ae03-4581604138fc",
    #         "location": {
    #             "key": "37",
    #             "description": "李总办公室；董事长；李总房间；董事长办公室"
    #         },
    #         "device": {
    #             "key": "climate.qjiang_cn_741478700_wb20",
    #             "description": "空调；制冷设备"
    #         },
    #         "operation": {
    #             "key": "set_temperature",
    #             "description": "设置温度;调节温度；"
    #         },
    #         "operation_params": []
    #     },
    #     "score": 0.9385,
    #     "confidence": "高"
    # }
    
    # result1 = device_op.get_operation_analysis_result(tool_data_en, best_match_data)
    # logger.info(f"测试1 - 纯英文操作: {result1}")  # 应该返回 "turn_on"
    
    # # 测试用例2：tool_data 包含中文操作
    # tool_data_cn = {
    #     "location": "办公室",
    #     "device": "空调", 
    #     "operation": "打开空调",
    #     "keyId": "1932095424144715777"
    # }
    
    # result2 = device_op.get_operation_analysis_result(tool_data_cn, best_match_data)
    # logger.info(f"测试2 - 中文操作: {result2}")  # 应该返回 "set_temperature"
    
    # # 测试用例3：tool_data 操作为空，使用 best_match
    # tool_data_empty = {
    #     "location": "office",
    #     "device": "air_conditioner",
    #     "operation": "",
    #     "keyId": "1932095424144715777"
    # }
    
    # result3 = device_op.get_operation_analysis_result(tool_data_empty, best_match_data)
    # logger.info(f"测试3 - 空操作: {result3}")  # 应该返回 "set_temperature"
