package com.fuyuanshen.global.mqtt.rule.bjq;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fuyuanshen.common.core.constant.GlobalConstants;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.core.utils.date.DurationUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.bo.DeviceAlarmBo;
import com.fuyuanshen.equipment.domain.vo.DeviceAlarmVo;
import com.fuyuanshen.equipment.service.DeviceService;
import com.fuyuanshen.equipment.service.IDeviceAlarmService;
import com.fuyuanshen.global.mqtt.base.MqttMessageRule;
import com.fuyuanshen.global.mqtt.base.MqttRuleContext;
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants;
import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.Date;
import java.util.concurrent.CompletableFuture;

import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.*;

/**
 * 灯光模式订阅设备回传消息
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class BjqModeRule implements MqttMessageRule {

    private final DeviceService deviceService;
    private final IDeviceAlarmService deviceAlarmService;


    @Override
    public String getCommandType() {
        return LightingCommandTypeConstants.LIGHT_MODE;
    }

    @Override
    public void execute(MqttRuleContext context) {
        String functionAccess = FUNCTION_ACCESS_KEY + context.getDeviceImei();
        try {
            Object[] convertArr = context.getConvertArr();

            String mainLightMode = convertArr[1].toString();
            String batteryRemainingTime = convertArr[2].toString();
            if (StringUtils.isNotBlank(mainLightMode)) {
                log.info("设备离线mainLightMode：{}", mainLightMode);
                if ("0".equals(mainLightMode)) {

                    // 设备离线
                    String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + context.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX;
                    RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "0");

                    String sendMessageIng = GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + context.getDeviceImei() + ":messageSending";
                    String messageSendingValue = RedisUtils.getCacheObject(sendMessageIng);
                    if ("1".equals(messageSendingValue)) {
                        // 设置为故障状态
                        RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "2");
                        UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
                        updateWrapper.eq("device_imei", context.getDeviceImei());
                        updateWrapper.set("online_status", 2);
                        deviceService.update(updateWrapper);
                        RedisUtils.deleteObject(sendMessageIng);

                        // 解除告警
                        String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + context.getDeviceImei() + DEVICE_ALARM_KEY_PREFIX;
                        if (RedisUtils.getCacheObject(deviceRedisKey) != null) {
                            RedisUtils.deleteObject(deviceRedisKey);
                        }
                        cancelAlarm(context.getDeviceImei());
                    }
                }
                // 发送设备状态和位置信息到Redis
                syncSendDeviceDataToRedisWithFuture(context.getDeviceImei(), mainLightMode);
                String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + context.getDeviceImei() + DEVICE_LIGHT_BRIGHTNESS_KEY_PREFIX;

                // 存储到Redis
                RedisUtils.setCacheObject(deviceRedisKey, batteryRemainingTime);
            }
            RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.OK.getCode(), Duration.ofSeconds(20));
        } catch (Exception e) {
            log.error("处理灯光模式命令时出错", e);
            RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.FAILED.getCode(), Duration.ofSeconds(20));
        }
    }

    /**
     * 发送设备状态信息和位置信息到Redis
     *
     * @param deviceImei 设备IMEI
     */
    public void syncSendDeviceDataToRedisWithFuture(String deviceImei, Object convertValue) {
//        CompletableFuture.runAsync(() -> {
//
//        });
        try {
            // 将设备状态信息存储到Redis中
            String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + deviceImei + DEVICE_LIGHT_MODE_KEY_PREFIX;

            // 存储到Redis
            RedisUtils.setCacheObject(deviceRedisKey, convertValue.toString());

        } catch (Exception e) {
            log.error("异步发送设备信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e);
        }
    }


    /**
     * 解除告警
     *
     * @param deviceImei 设备IMEI
     */

    public void cancelAlarm(String deviceImei) {
        DeviceAlarmVo deviceAlarmVo = deviceAlarmService.queryLatestByDeviceImei(deviceImei);
        DeviceAlarmBo deviceAlarmBo = new DeviceAlarmBo();
        if (deviceAlarmVo != null) {
            if (deviceAlarmVo.getFinishTime() == null) {
                BeanUtil.copyProperties(deviceAlarmVo, deviceAlarmBo);
                deviceAlarmBo.setFinishTime(new Date());
                String durationBetween = DurationUtils.getDurationBetween(deviceAlarmVo.getStartTime(), deviceAlarmBo.getFinishTime());
                deviceAlarmBo.setDurationTime(durationBetween);
                // 0已处理，1未处理
                deviceAlarmBo.setTreatmentState(0);
                // 告警状态，0 解除告警， 1 告警中
                deviceAlarmBo.setAlarmState(0);
                deviceAlarmService.updateByBo(deviceAlarmBo);
            }
        }
    }


}
