package com.xzzn.framework.aspectj;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsFaultProtectionPlan;
import com.xzzn.ems.domain.MqttSyncLog;
import com.xzzn.ems.mapper.EmsFaultProtectionPlanMapper;
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
import com.xzzn.ems.mapper.MqttSyncLogMapper;
import com.xzzn.framework.web.service.MqttPublisher;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 设备保护告警方案同步
 * 云端 - 本地
 */
@Aspect
@Component
public class FaultProtPlanAspect {
    private static final Log logger = LogFactory.getLog(FaultProtPlanAspect.class);
    @Autowired
    private MqttPublisher mqttPublisher;

    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final String MQTT_TOPIC = "FAULT_PROTECTION_PLAN_UP";
    private static final String TABLE_NAME = "ems_fault_protection_plan";
    @Autowired
    private EmsMqttTopicConfigMapper emsMqttTopicConfigMapper;
    @Autowired
    private MqttSyncLogMapper mqttSyncLogMapper;
    @Autowired
    private EmsFaultProtectionPlanMapper emsFaultProtectionPlanMapper;

    // 用ThreadLocal暂存删除前的对象
    private ThreadLocal<EmsFaultProtectionPlan> beforeDeleteThreadLocal = new ThreadLocal<>();
    @Before("execution(* com.xzzn.ems.mapper.EmsFaultProtectionPlanMapper.deleteEmsFaultProtectionPlanByIds(..)) &&  args(ids)")
    public void beforeDelete(JoinPoint joinPoint, Long[] ids) {
        // 获取删除的id
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            return;
        }
        Long[] id = (Long[]) args[0];

        // 查询删除前的数据
        EmsFaultProtectionPlan faultInfo = emsFaultProtectionPlanMapper.selectEmsFaultProtectionPlanById(id[0]);
        beforeDeleteThreadLocal.set(faultInfo); // 暂存
    }

    // 定义切点：拦截策略相关表的Mapper方法
    @Pointcut("(execution(* com.xzzn.ems.mapper.EmsFaultProtectionPlanMapper.insertEmsFaultProtectionPlan(..)) &&  args(insertEntity)) ")
    public void insertPointCut(EmsFaultProtectionPlan insertEntity) {
        logger.info("【新增设备保护告警】FaultProtPlanAspect 实例化");
    }
    @Pointcut("(execution(* com.xzzn.ems.mapper.EmsFaultProtectionPlanMapper.updateEmsFaultProtectionPlan(..)) &&  args(updateEntity)) ")
    public void updatePointCut(EmsFaultProtectionPlan updateEntity) {
        logger.info("【更新设备保护告警】FaultProtPlanAspect 实例化");
    }
    @Pointcut("(execution(* com.xzzn.ems.mapper.EmsFaultProtectionPlanMapper.deleteEmsFaultProtectionPlanByIds(..)) &&  args(ids)) ")
    public void deletePointCut(Long[] ids) {
        logger.info("【删除设备保护告警】FaultProtPlanAspect 实例化");
    }

    // 方法执行成功后发布同步消息
    @AfterReturning(pointcut = "insertPointCut(insertEntity)", returning = "result")
    public void afterInsert(JoinPoint joinPoint, EmsFaultProtectionPlan insertEntity, Integer result) {
        logger.info("【新增设备保护告警切面进入成功】");
        if (result == 0 || insertEntity == null) {
            return;
        }

        // 校验是否配置监听topic-监听则不发布
        String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
        if (!StringUtils.isEmpty(topic)) {
            return;
        }

        // 解析方法名，获取操作类型（INSERT/UPDATE/DELETE）和表名
        String methodName = joinPoint.getSignature().getName();
        String operateType = getOperateType(methodName);
        String siteId = insertEntity.getSiteId();

        // 构建日志同步消息
        MqttSyncLog message = createMessageObject(operateType,siteId);

        try {
            // 数据转换
            String content = convertEntityToJson(insertEntity);
            message.setContent(content);

            // 发布到MQTT主题
            mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
        } catch (Exception e) {
            message.setStatus("FAIL");
            message.setErrorMsg(e.getMessage());
        }
        // 存储同步信息
        mqttSyncLogMapper.insertMqttSyncLog(message);
    }
    @AfterReturning(pointcut = "updatePointCut(updateEntity)", returning = "result")
    public void afterUpdate(JoinPoint joinPoint, EmsFaultProtectionPlan updateEntity, Integer result) {
        logger.info("【更新设备保护告警切面进入成功】");
        if (result == 0 || updateEntity == null) {
            return;
        }
        // 校验是否配置监听topic-监听则不发布
        String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
        if (!StringUtils.isEmpty(topic)) {
            return;
        }

        // 解析方法名，获取操作类型（INSERT/UPDATE/DELETE）和表名
        String methodName = joinPoint.getSignature().getName();
        String operateType = getOperateType(methodName);
        String siteId = updateEntity.getSiteId();

        // 构建日志同步消息
        MqttSyncLog message = createMessageObject(operateType,siteId);

        try {
            // 数据转换
            String content = convertEntityToJson(updateEntity);
            message.setContent(content);

            // 发布到MQTT主题
            mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
        } catch (Exception e) {
            message.setStatus("FAIL");
            message.setErrorMsg(e.getMessage());
        }
        // 存储同步信息
        mqttSyncLogMapper.insertMqttSyncLog(message);
    }
    @AfterReturning(pointcut = "deletePointCut(id)", returning = "result")
    public void afterDelete(JoinPoint joinPoint, Long[] id, Integer result) {
        logger.info("【删除设备保护告警切面进入成功】");
        if (result == 0 || id == null) {
            return;
        }
        // 校验是否配置监听topic-监听则不发布
        String topic = emsMqttTopicConfigMapper.checkTopicIsExist(MQTT_TOPIC);
        if (!StringUtils.isEmpty(topic)) {
            return;
        }

        // 解析方法名，获取操作类型（INSERT/UPDATE/DELETE）和表名
        String methodName = joinPoint.getSignature().getName();
        String operateType = getOperateType(methodName);

        // 从ThreadLocal中获取删除前的对象
        EmsFaultProtectionPlan faultInfo = beforeDeleteThreadLocal.get();
        if (faultInfo == null) {
            return;
        }

        // 构建日志同步消息
        MqttSyncLog message = createMessageObject(operateType,faultInfo.getSiteId());

        try {
            // 数据转换
            String content = convertEntityToJson(faultInfo);
            message.setContent(content);

            // 发布到MQTT主题
            mqttPublisher.publish(MQTT_TOPIC, objectMapper.writeValueAsString(message), 1);
        } catch (Exception e) {
            message.setStatus("FAIL");
            message.setErrorMsg(e.getMessage());
        }
        // 存储同步信息
        mqttSyncLogMapper.insertMqttSyncLog(message);
    }

    // 构建同步信息
    private MqttSyncLog createMessageObject(String operateType, String siteId) {
        MqttSyncLog message = new MqttSyncLog();
        message.setSyncId(UUID.randomUUID().toString());
        message.setOperateType(operateType);
        message.setTableName(TABLE_NAME);
        message.setCreateTime(new Date());
        message.setTopic(MQTT_TOPIC);
        message.setStatus("SUCCESS");
        message.setSyncObject("CLOUD");
        message.setTarget(siteId);
        return message;
    }

    // 从方法名判断操作类型（示例：insert→INSERT，update→UPDATE，delete→DELETE）
    private String getOperateType(String methodName) {
        if (methodName.startsWith("insert")) return "INSERT";
        if (methodName.startsWith("stop")) return "STOP";
        if (methodName.startsWith("update") || methodName.startsWith("stop")) return "UPDATE";
        if (methodName.startsWith("delete")) return "DELETE";
        return "UNKNOWN";
    }

    // 从方法参数提取数据（示例：若参数是实体类，转成Map）
    private Map<String, Object> extractDataFromParams(Object[] args) {
        // 实际需反射获取实体类的字段和值（如id、name等）
        Map<String, Object> data = new HashMap<>();
        if (args == null || args.length == 0) {
            return data;
        }

        for (int i = 0; i < args.length; i++) {
            Object arg = args[i];
            if (arg == null) {
                continue; // 跳过null参数
            }

            // 处理基本类型/包装类/字符串（直接作为值存入，key为"param0"、"param1"等）
            if (isBasicType(arg.getClass())) {
                String key = "param" + i; // 基本类型参数用"param0"、"param1"作为key
                data.put(key, arg);
            } else {
                Map<String, Object> beanMap = beanToMap(arg);
                data.putAll(beanMap); // 合并实体类的字段到结果Map
            }
        }

        return data;
    }

    /**
     * 判断是否为基本类型或包装类或字符串
     */
    private boolean isBasicType(Class<?> clazz) {
        return clazz.isPrimitive() // 基本类型（int、long、boolean等）
                || clazz == String.class // 字符串
                || Number.class.isAssignableFrom(clazz) // 数字包装类（Integer、Long等）
                || clazz == Boolean.class; // 布尔包装类
    }

    /**
     * 将实体类转换为Map（字段名为key，字段值为value）
     */
    private Map<String, Object> beanToMap(Object bean) {
        Map<String, Object> map = new HashMap<>();
        if (bean == null) {
            return map;
        }

        // 方式1：使用BeanMap（简洁高效）
        BeanMap beanMap = BeanMap.create(bean);
        for (Object key : beanMap.keySet()) {
            map.put(key.toString(), beanMap.get(key));
        }

        return map;
    }

    // 在方法中转换
    public String convertEntityToJson(EmsFaultProtectionPlan insertEntity) throws Exception {
        if (insertEntity == null) {
            return null; // 空对象返回空JSON
        }

        // 将实体类转换为JSON字符串
        return objectMapper.writeValueAsString(insertEntity);
    }


}