package com.agri.framework.interceptor;

import com.agri.framework.config.MqttConfig;
import com.agri.system.domain.SysRollerAir;
import com.agri.system.service.*;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import org.apache.commons.lang3.ObjectUtils;
import org.checkerframework.checker.units.qual.A;
import org.eclipse.paho.client.mqttv3.MqttException;
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.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class FrontendConfigHandler {

    private static final Logger log = LoggerFactory.getLogger(FrontendConfigHandler.class);

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private MqttConfig.MqttMessageSender mqttMessageSender;

    @Autowired
    private ISysRollerAirService sysRollerAirService;

    @Value("${spring.mqtt.dtu-ctl-lock-ttl}")
    private int dtuCtlLockTTL;

    @Value("${agri.per-lap.len}")
    private BigDecimal perLapLen;

    @Value("${agri.per-lap.sec}")
    private BigDecimal perLapSec;
    /**
     * 处理前端控制指令：权限校验+分布式锁+转发给设备
     */
    public void handle(String topic, String payload) throws MqttException {
        // 解析前端clientId、设备ID
        String[] parts = topic.split("/");
        String clientId = parts[1];
        String deviceId = parts[2];

        // 新增：入参非空校验（JDK 8兼容）
        if (!StringUtils.hasText(clientId) || !StringUtils.hasText(deviceId)) {
            log.error("【指令处理】clientId或deviceId为空，topic={}", topic);
            return;
        }
        // 解析功能码（{"功能码":状态码}格式）
        Map<String, Integer> funcCodeMap = null;
        try {
            funcCodeMap = JSON.parseObject(payload, new TypeReference<Map<String, Integer>>() {
            });
        } catch (Exception e) {
            log.error("【指令处理】功能码解析失败，payload={}", payload, e);
            return;
        }
        if (funcCodeMap == null || funcCodeMap.isEmpty()) {
            log.warn("【指令处理】前端{}操作设备{}失败：功能码为空", clientId, deviceId);
            return;
        }
        // 提取第一个功能码作为锁标识
        String funcType = funcCodeMap.keySet().iterator().next();

        // 2. 分布式锁：设备ID+功能类型（避免同设备同功能并发控制）
        String lockKey = "lock:" + deviceId + ":" + funcType;
        Boolean lockSuccess = stringRedisTemplate.opsForValue().setIfAbsent(
                lockKey, clientId, dtuCtlLockTTL, TimeUnit.SECONDS // 延长至15秒，适配设备回执场景
        );
        if (lockSuccess == null || !lockSuccess) {
            String errorTopic = "frontend/" + clientId + "/dtu/" + deviceId + "/listener";
            mqttMessageSender.publish(errorTopic, "{\"msg\":\"设备" + funcType + "功能忙，请稍后重试\",\"clientId\":\""+clientId+"\"}");
            log.warn("【分布式锁】前端{}操作设备{}的{}功能失败；可能其他用户正在操作此功能", clientId, deviceId, funcType);
            return;
        }
       try {
           //  转发前端指令
           String deviceTopic = "dtu/" + deviceId + "/down";
           mqttMessageSender.publish(deviceTopic, payload);
           LocalDateTime currentTime = LocalDateTime.now();
           // 3. 记录日志
           log.info("【指令处理】前端{}于{}控制设备{}的{}功能，指令：{}",
                   clientId, currentTime, deviceId, funcType, payload);

           String funcName = funcType.substring(0, funcType.length() - 1);
           Integer funcCode = funcCodeMap.get(funcType);

           // 当卷膜 开 暂停，才执行的逻辑
           if (funcCode == 0 && funcType.contains("k")) {
               SysRollerAir sysRollerAir = sysRollerAirService.lambdaQuery()
                       .eq(SysRollerAir::getImei, deviceId)
                       .eq(SysRollerAir::getRoller, funcName)
                       .eq(SysRollerAir::getOpType, 1)
                       .orderByDesc(SysRollerAir::getId)
                       .last("limit 1")
                       .one();
               BigDecimal ventTotalLen = BigDecimal.ZERO;
               if (ObjectUtils.isNotEmpty(sysRollerAir)
                       && sysRollerAir.getOpTime().isBefore(currentTime)) {

                   long time = Math.abs(Duration.between(currentTime, sysRollerAir.getOpTime()).getSeconds());
                   BigDecimal ventTotalTime = BigDecimal.valueOf(time);

                   // 除以一圈的时间乘以一圈的长度
                   ventTotalLen = ventTotalTime.divide(perLapSec, 2, RoundingMode.HALF_UP)
                           .multiply(perLapLen).setScale(2, RoundingMode.HALF_UP);
                   log.info("【自动化参数】卷膜校准时间：{}; 一圈秒数：{}; 一圈长度: {}", ventTotalTime,perLapSec,perLapLen);
               }
               String config = "{\"ventTotalLen\": " + ventTotalLen +",\"clientId\":\""+clientId+"\"}";
               // 查数据库、最后一条卷膜开暂停。计算时间发送自动关时间
               mqttMessageSender.publish("frontend/"+clientId+"/dtu/"+deviceId+"/config", config);
           }
           // 插入记录
           SysRollerAir rollerAir = new SysRollerAir();
           rollerAir.setImei(deviceId);
           rollerAir.setRoller(funcName);
           rollerAir.setOpType(funcCode);
           rollerAir.setPayload(payload);
           rollerAir.setClientid(clientId);
           rollerAir.setOpTime(currentTime);
           sysRollerAirService.save(rollerAir);
           log.info("【指令转发】前端{} → 设备{}的{}功能", clientId, deviceId, funcType);
       } finally {
           stringRedisTemplate.delete(lockKey);
       }
    }
}
