package com.agri.framework.interceptor;

import com.agri.framework.manager.MqttAutoOffManager;
import com.agri.system.domain.SysAgriLimit;
import com.agri.system.domain.SysDevOperLog;
import com.agri.system.service.ISysAgriLimitService;
import com.agri.system.service.ISysDevOperLogService;
import com.alibaba.fastjson2.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

@Component
public class DeviceAckHandler {
    /**
     * 优化：统一使用SLF4J日志（JDK 8兼容）
     */
    private static final Logger log = LoggerFactory.getLogger(DeviceAckHandler.class);

    /**
     * Redis模板，用于存储订阅关系、设备在线状态、分布式锁
     */
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 自动关任务管理器，调度/取消自动关任务
     */
    @Resource
    private MqttAutoOffManager mqttAutoOffManager;

    /**
     * 农业限制服务，查询设备自动关延迟配置
     */
    @Resource
    private ISysAgriLimitService agriLimitService;

    @Autowired
    private ISysDevOperLogService sysDevOperLogService;


    // 初始化映射（建议放在类初始化块/构造方法中，只初始化一次）
    private static final Map<String, Function<SysAgriLimit, Integer>> LIMIT_MAP = new HashMap<>();
    private static final Set<String> VALID_FUNC_CODES = new HashSet<>();
    static {
        LIMIT_MAP.put("jm1g1", agriLimit -> Integer.parseInt(String.valueOf(agriLimit.getJm1gLimit())));
        LIMIT_MAP.put("jm2g1", agriLimit -> Integer.parseInt(String.valueOf(agriLimit.getJm2gLimit())));
        LIMIT_MAP.put("jbg1", agriLimit -> Integer.parseInt(String.valueOf(agriLimit.getJbgLimit())));
        LIMIT_MAP.put("jm3g1", agriLimit -> Integer.parseInt(String.valueOf(agriLimit.getJm3gLimit())));
        LIMIT_MAP.put("jm2k1", agriLimit -> Integer.parseInt(String.valueOf(agriLimit.getJm2kLimit())));
        LIMIT_MAP.put("jm3k1", agriLimit -> Integer.parseInt(String.valueOf(agriLimit.getJm3kLimit())));
        LIMIT_MAP.put("jbk1", agriLimit -> Integer.parseInt(String.valueOf(agriLimit.getJbkLimit())));
        LIMIT_MAP.put("jm1k1", agriLimit -> Integer.parseInt(String.valueOf(agriLimit.getJm1kLimit())));

        VALID_FUNC_CODES.add("jm1g");
        VALID_FUNC_CODES.add("jm2g");
        VALID_FUNC_CODES.add("jbg");
        VALID_FUNC_CODES.add("jm3g");
        VALID_FUNC_CODES.add("jm2k");
        VALID_FUNC_CODES.add("jm3k");
        VALID_FUNC_CODES.add("jbk");
        VALID_FUNC_CODES.add("jm1k");
    }

    public void isStartAutoOffTask(JSONObject payloadObj, String deviceId, String payload) {
        if (payloadObj.containsKey("suc") && payloadObj.containsKey("prop")) {
            JSONObject propObj = payloadObj.getJSONObject("prop");
            if (propObj != null && !propObj.isEmpty()) {
                boolean suc = payloadObj.getBooleanValue("suc");

                for (Map.Entry<String, Object> propEntry : propObj.entrySet()) {
                    String funcType = propEntry.getKey();
                    Integer funcValue = parseFuncValue(propEntry.getValue());

                    processAck(deviceId, funcType, funcValue, suc);
                }

                if (propObj.size() > 1) {
                    log.info("【设备回执】设备{}的{}个功能已处理", deviceId, propObj.size());
                }
            }
        }
    }

    private void processAck(String deviceId, String funcType, Integer funcValue, boolean suc) {
        String lockKey = "lock:" + deviceId + ":" + funcType;
        Boolean delete = stringRedisTemplate.delete(lockKey);
        log.info("【设备回执】设备{}的{}功能执行完成，已释放锁：{},{}", deviceId, funcType, lockKey, delete);

        int runTime = 0;
        if (suc && StringUtils.hasText(funcType) && funcValue != null && funcValue == 1) {
            SysAgriLimit agriLimit = agriLimitService.lambdaQuery()
                    .eq(SysAgriLimit::getImei, deviceId)
                    .one();
            if (agriLimit != null) {
                int autoOffSeconds = LIMIT_MAP.getOrDefault(funcType, k -> 0).apply(agriLimit);
                runTime = autoOffSeconds;
                if (autoOffSeconds > 0) {
                    mqttAutoOffManager.scheduleAutoOff(deviceId, funcType, autoOffSeconds);
                    log.debug("【自动关任务】标记需要执行，deviceId={}, funcType={}, delay={}s", deviceId, funcType, autoOffSeconds);
                }
            }
        }

        if (suc && StringUtils.hasText(funcType) && funcValue != null && funcValue == 0) {
            mqttAutoOffManager.cancelAutoOff(deviceId, funcType);
        }

        boolean isTask = (Objects.equals(funcValue, 1)) && (runTime > 0);
        sysDevOperLogService.lambdaUpdate()
                .eq(SysDevOperLog::getImei, deviceId)
                .eq(SysDevOperLog::getFuncCode, funcType)
                .eq(SysDevOperLog::getOpType, funcValue)
                .eq(SysDevOperLog::getLockAcquired, 1)
                .orderByDesc(SysDevOperLog::getCreateTime)
                .last("LIMIT 1")
                .set(SysDevOperLog::getAckReceived, 1)
                .set(SysDevOperLog::getAckSuc, suc ? 1 : 0)
                .set(SysDevOperLog::getIsLockSuc, delete ? 1 : 0)
                .set(SysDevOperLog::getIsTask, isTask ? 1 : 0)
                .set(isTask, SysDevOperLog::getRunTime, runTime)
                .set(isTask, SysDevOperLog::getNoTaskReason, runTime > 0 ? null : "【自动关任务】标记不符合执行运行时间未配置，当前运行时间：【" + runTime + " s】")
                .set(SysDevOperLog::getUpdateBy, "设备回执")
                .set(SysDevOperLog::getAck, "{funcType:" + funcType + ", value:" + funcValue + "}")
                .update();
    }

    private Integer parseFuncValue(Object value) {
        if (value == null) {
            return null;
        }
        try {
            return Integer.parseInt(String.valueOf(value));
        } catch (NumberFormatException e) {
            return null;
        }
    }

}