package com.fuyuanshen.global.mqtt.listener;

import cn.hutool.core.thread.ThreadUtil;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import com.baomidou.lock.executor.RedissonLockExecutor;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.redis.utils.RedisUtils;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.time.Duration;

import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_TIMEOUT_KEY;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX;

@Component
@Slf4j
public class RedisKeyExpirationListener implements MessageListener {

    @Autowired
    @Qualifier("threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private LockTemplate lockTemplate;

    @Override
    public void onMessage(Message message, byte[] pattern) {
        String expiredKey = new String(message.getBody());

        if (expiredKey.startsWith(FUNCTION_ACCESS_KEY)) {
            String element = expiredKey.substring(FUNCTION_ACCESS_KEY.length());
            handleFunctionAccessExpired(element);
        }
        if(expiredKey.endsWith(DEVICE_ONLINE_STATUS_KEY_PREFIX)) {

            threadPoolTaskExecutor.execute(() -> {
                log.info("设备离线：{}", expiredKey);
                String element = expiredKey.substring(GlobalConstants.GLOBAL_REDIS_KEY.length() + DEVICE_KEY_PREFIX.length(), expiredKey.length() - DEVICE_ONLINE_STATUS_KEY_PREFIX.length());

                // 构造设备锁键
                String deviceLockKey = GlobalConstants.GLOBAL_REDIS_KEY + ":device_lock:" + element;

                // 尝试获取Redis锁
                LockInfo lockInfo = lockTemplate.lock(deviceLockKey, 30000L, 5000L, RedissonLockExecutor.class); // 30秒过期

                if (lockInfo != null) {
                    try {
                        String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ message + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ;
//                        String deviceOnlineStatusRedis = RedisUtils.getCacheObject(deviceOnlineStatusRedisKey);
//                        if(StringUtils.isBlank(deviceOnlineStatusRedis)){
//                            UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
//                            deviceUpdateWrapper.eq("device_imei", element);
//                            deviceUpdateWrapper.set("online_status", 0);
//                            deviceMapper.update(deviceUpdateWrapper);
//                        }else{
//                            RedisUtils.deleteObject(deviceOnlineStatusRedisKey);
//                        }

                        UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
                        deviceUpdateWrapper.eq("device_imei", element);
                        deviceUpdateWrapper.set("online_status", 0);
                        deviceMapper.update(deviceUpdateWrapper);
                        String deviceOnlineStatusRedis = RedisUtils.getCacheObject(deviceOnlineStatusRedisKey);
                        if(StringUtils.isNotBlank(deviceOnlineStatusRedis)){
                            RedisUtils.deleteObject(deviceOnlineStatusRedisKey);
                        }
                    } finally {
                        //释放锁
                        lockTemplate.releaseLock(lockInfo);
                    }
                } else {
                    log.warn("无法获取设备锁，跳过设备离线处理: {}", element);
                }
            });
        }


    }
    /**
     * 访问key过期事件
     * @param element 批次ID
     */
    private void handleFunctionAccessExpired(String element) {
        RedisUtils.setCacheObject(FUNCTION_ACCESS_TIMEOUT_KEY + element, FunctionAccessStatus.TIMEOUT.getCode(), Duration.ofSeconds(30L));
    }
}
