package com.fuyuanshen.web.service.device;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fuyuanshen.app.domain.vo.AppDeviceHBY100JDetailVo;
import com.fuyuanshen.app.mapper.AppDeviceShareMapper;
import com.fuyuanshen.common.core.constant.GlobalConstants;
import com.fuyuanshen.common.core.domain.model.AppLoginUser;
import com.fuyuanshen.common.core.domain.model.LoginUser;
import com.fuyuanshen.common.core.exception.ServiceException;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
import com.fuyuanshen.common.satoken.utils.LoginHelper;
import com.fuyuanshen.equipment.domain.AppBusinessFile;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.domain.vo.AppBusinessFileVo;
import com.fuyuanshen.equipment.mapper.AppBusinessFileMapper;
import com.fuyuanshen.equipment.mapper.DeviceLogMapper;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
import com.fuyuanshen.equipment.service.IAppBusinessFileService;
import com.fuyuanshen.global.mqtt.config.MqttGateway;
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
import com.fuyuanshen.global.mqtt.constants.MqttConstants;
import com.fuyuanshen.global.mqtt.rule.hby100j.domin.*;
import com.fuyuanshen.global.mqtt.utils.GenerateIdUtil;
import com.fuyuanshen.system.domain.vo.SysOssVo;
import com.fuyuanshen.system.mapper.SysOssMapper;
import com.fuyuanshen.web.controller.device.domain.dto.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX;


@Slf4j
@Service
@RequiredArgsConstructor
public class DeviceHBY100JBizService {

    private final DeviceMapper deviceMapper;
    private final DeviceTypeMapper deviceTypeMapper;
    private final MqttGateway mqttGateway;
    private final DeviceLogMapper deviceLogMapper;
    private final IAppBusinessFileService appBusinessFileService;
    private final AppBusinessFileMapper appBusinessFileMapper;
    private final SysOssMapper sysOssMapper;
    private final AppDeviceShareMapper appDeviceShareMapper;


    private static final String DEVICE_TYPE = "HBY100/";

    private static final Long pcUserId = 0L;
    /**
     * 记录设备操作日志
     *
     * @param deviceId 设备ID
     * @param content  日志内容
     * @param operator 操作人
     */
    private void recordDeviceLog(Long deviceId, String deviceName, String deviceAction, String content, Long operator) {
        try {
            // 创建设备日志实体
            com.fuyuanshen.equipment.domain.DeviceLog deviceLog = new com.fuyuanshen.equipment.domain.DeviceLog();
            deviceLog.setDeviceId(deviceId);
            deviceLog.setDeviceAction(deviceAction);
            deviceLog.setContent(content);
            deviceLog.setCreateBy(operator);
            deviceLog.setDeviceName(deviceName);
            deviceLog.setCreateTime(new Date());

            // 插入日志记录
            deviceLogMapper.insert(deviceLog);
        } catch (Exception e) {
            log.error("记录设备操作日志失败: {}", e.getMessage(), e);
        }
    }


    public AppDeviceHBY100JDetailVo getInfo(Long id) {
        Device device = deviceMapper.selectById(id);
        if (device == null) {
            throw new RuntimeException("请先将设备入库！！！");
        }

        AppDeviceHBY100JDetailVo vo = new AppDeviceHBY100JDetailVo();
        vo.setDeviceId(device.getId());
        vo.setDeviceName(device.getDeviceName());
        vo.setDevicePic(device.getDevicePic());
        vo.setDeviceImei(device.getDeviceImei());
        vo.setDeviceMac(device.getDeviceMac());
        DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
        if (deviceType != null) {
            vo.setCommunicationMode(Integer.valueOf(deviceType.getCommunicationMode()));
            vo.setTypeName(deviceType.getTypeName());
        }
        vo.setBluetoothName(device.getBluetoothName());

        // 设备在线状态
        String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX);
        // 设备在线状态
        if ("1".equals(onlineStatus)) {
            vo.setOnlineStatus(1);
        } else if ("2".equals(onlineStatus)) {
            vo.setOnlineStatus(2);
        } else {
            vo.setOnlineStatus(0);
        }

        String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX);
        // 获取电量
        if (StringUtils.isNotBlank(deviceStatus)) {
            JSONObject jsonObject = JSONObject.parseObject(deviceStatus);
            vo.setBatteryPercentage(jsonObject.getInteger("batteryPercentage"));
            vo.setChargeState(jsonObject.getInteger("chargeState"));
            vo.setBatteryRemainingTime(jsonObject.getInteger("batteryRemainingTime"));
        } else {
            vo.setBatteryPercentage(0);
            vo.setBatteryRemainingTime(0);
        }



        String reportStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + ":report");
        if (StringUtils.isNotBlank(reportStatus)) {
            FuncType14StatusReport report = JSONObject.parseObject(reportStatus,FuncType14StatusReport.class);
            FuncType14StatusReport.Data data = report.getData();
            FuncType14StatusReport.Brightness brightness = data.getBrightness();
            if(brightness != null){
                vo.setLightBrightness(brightness.getRed());
            }

            vo.setVolume(data.getVolume());
            FuncType14StatusReport.LedStrobe ledStrobe = data.getLedStrobe();
            if(ledStrobe != null){
                vo.setStrobeFrequency(ledStrobe.getFrequency());
                vo.setStrobeMode(ledStrobe.getMode());
                vo.setStrobeEnable(ledStrobe.getEnable());
            }


            Integer voiceBroadcast = data.getVoiceBroadcast();
            if(voiceBroadcast != null){
                vo.setVoiceBroadcast(voiceBroadcast);
            }
            FuncType14StatusReport.SirenAlarm sirenAlarm = data.getSirenAlarm();
            if(sirenAlarm != null){
                vo.setVoiceStrobeAlarm(sirenAlarm.getEnable());
                vo.setAlarmMode(sirenAlarm.getMode());
            }
        }

        String voicePlayRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
                device.getDeviceImei() + ":voicePlay";
        String voicePlayStatus = RedisUtils.getCacheObject(voicePlayRedisKey);
        if(StringUtils.isNotBlank(voicePlayStatus)){
            FuncType6VoicePlayRequest funcType6VoicePlayRequest = JSONObject.parseObject(voicePlayStatus, FuncType6VoicePlayRequest.class);
            if(funcType6VoicePlayRequest.getData() != null){
                vo.setVoiceBroadcast(funcType6VoicePlayRequest.getData().getVoiceBroadcast());
            }
        }

        String strobeModeRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
                device.getDeviceImei() + ":strobeMode";
        String strobeModeStatus = RedisUtils.getCacheObject(strobeModeRedisKey);
        if(StringUtils.isNotBlank(strobeModeStatus)){
            FuncType10StrobeModeRequest strobeModeRequest = JSONObject.parseObject(strobeModeStatus, FuncType10StrobeModeRequest.class);
            FuncType10StrobeModeRequest.Data data = strobeModeRequest.getData();
            if(data != null){
                vo.setStrobeMode(strobeModeRequest.getData().getMode());
                vo.setStrobeEnable(strobeModeRequest.getData().getEnable());
            }
        }

        String updateVolumeRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
                device.getDeviceImei() + ":updateVolume";
        String updateVolumeStatus = RedisUtils.getCacheObject(updateVolumeRedisKey);
        if(StringUtils.isNotBlank(updateVolumeStatus)){
            FuncType9UpdateVolumeRequest updateVolumeRequest = JSONObject.parseObject(updateVolumeStatus, FuncType9UpdateVolumeRequest.class);
            if(updateVolumeRequest.getData() != null){
                vo.setVolume(updateVolumeRequest.getData().getVolume());
            }
        }

        String frequencyRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
                device.getDeviceImei() + ":frequency";
        String frequencyStatus = RedisUtils.getCacheObject(frequencyRedisKey);
        if(StringUtils.isNotBlank(frequencyStatus)){
            FuncType11FrequencyRequest frequencyRequest = JSONObject.parseObject(frequencyStatus, FuncType11FrequencyRequest.class);
            if(frequencyRequest.getData() != null){
                vo.setStrobeFrequency(frequencyRequest.getData().getFrequency());
            }
        }

        String forceAudioRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
                device.getDeviceImei() + ":forceAudio";
        String forceAudioStatus = RedisUtils.getCacheObject(forceAudioRedisKey);
        if(StringUtils.isNotBlank(forceAudioStatus)){
            FuncType12ForceAudioRequest forceAudioRequest = JSONObject.parseObject(forceAudioStatus, FuncType12ForceAudioRequest.class);
            if(forceAudioRequest.getData() != null){
                vo.setVoiceStrobeAlarm(forceAudioRequest.getData().getVoiceStrobeAlarm());
                vo.setAlarmMode(forceAudioRequest.getData().getMode());
            }
        }


        // 获取经度纬度

        String location = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_LOCATION_KEY_PREFIX);
        if (StringUtils.isNotBlank(location)) {
            JSONObject jsonObject = JSONObject.parseObject(location);
            vo.setLatitude(jsonObject.getString("latitude"));
            vo.setLongitude(jsonObject.getString("longitude"));
            vo.setAddress(jsonObject.getString("address"));
        }

        QueryWrapper<AppBusinessFile> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("business_id", device.getId());
        queryWrapper.eq("file_type", 3);
        queryWrapper.eq("use_status", 1);
        List<AppBusinessFile> appBusinessFiles = appBusinessFileMapper.selectList(queryWrapper);
        if(appBusinessFiles != null && appBusinessFiles.size() > 0){
            AppBusinessFile appBusinessFile = appBusinessFiles.get(0);
            SysOssVo sysOssVo = sysOssMapper.selectVoById(appBusinessFile.getFileId());
            if(sysOssVo != null){
                vo.setVoiceResource(sysOssVo.getUrl());
            }
        }
        return vo;
    }


    private boolean getDeviceStatus(String deviceImei) {
        String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + deviceImei + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX;
        return RedisUtils.getCacheObject(deviceOnlineStatusRedisKey) == null;
    }


    public void forceAlarmActivation(HBY100JForceAlarmActivationDto bo) {
        List<Long> deviceIds = bo.getDeviceIds();
        if (deviceIds == null || deviceIds.isEmpty()) {
            throw new ServiceException("请选择设备");
        }
        AppLoginUser loginUser = AppLoginHelper.getLoginUser();
        bo.getDeviceIds().forEach(deviceId -> {
            Device deviceObj = deviceMapper.selectById(deviceId);
            if (getDeviceStatus(deviceObj.getDeviceImei())) {
                throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
            }

            FuncType12ForceAudioRequest  request = new FuncType12ForceAudioRequest();
            request.setRequestId(GenerateIdUtil.generateNumericId());
            request.setImei(deviceObj.getDeviceImei());
            request.setFuncType("12");
            request.setTimestamp(System.currentTimeMillis());
            FuncType12ForceAudioRequest.Data data = new FuncType12ForceAudioRequest.Data();
            data.setVoiceStrobeAlarm(bo.getVoiceStrobeAlarm());
            data.setMode(bo.getMode());
            request.setData(data);
            log.info("HBY100J强制报警，下发设备参数：{}", request);
            mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
            Long userId = loginUser == null ? pcUserId : loginUser.getUserId();

            recordDeviceLog(deviceId, deviceObj.getDeviceName(), "强制报警激活", "强制报警激活", userId);
        });

    }

    public void updateVoice(HBY100JUpdateVoiceDto dto) {
        AppBusinessFileVo appBusinessFileVo = appBusinessFileMapper.selectVoById(dto.getId());
        if(appBusinessFileVo == null){
            throw new ServiceException("文件不存在");
        }
        Device deviceObj = deviceMapper.selectById(appBusinessFileVo.getBusinessId());
        if (getDeviceStatus(deviceObj.getDeviceImei())) {
            throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
        }
        AppLoginUser loginUser = AppLoginHelper.getLoginUser();
        if(dto.getCommunicationMode()!=null && dto.getCommunicationMode()==0){
            SysOssVo sysOssVo = sysOssMapper.selectVoById(appBusinessFileVo.getFileId());
            FuncType5UpdateVoiceRequest  request = new FuncType5UpdateVoiceRequest();
            request.setRequestId(GenerateIdUtil.generateNumericId());
            request.setImei(deviceObj.getDeviceImei());
            request.setFuncType("5");
            request.setTimestamp(System.currentTimeMillis());
            FuncType5UpdateVoiceRequest.Data data = new FuncType5UpdateVoiceRequest.Data();
            data.setVoiceResource(sysOssVo.getUrl());
            data.setVoiceType(0);
            request.setData(data);
            log.info("HBY100J更新语音，参数：{}", request);

            mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
        }

        UpdateWrapper<AppBusinessFile> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("business_id", appBusinessFileVo.getBusinessId());
        updateWrapper.set("use_status", 0);
        appBusinessFileMapper.update(updateWrapper);

        UpdateWrapper<AppBusinessFile> updateWrapper2 = new UpdateWrapper<>();
        updateWrapper2.eq("id", appBusinessFileVo.getId());
        updateWrapper2.set("use_status", 1);
        appBusinessFileMapper.update(updateWrapper2);
        Long userId = loginUser == null ? pcUserId : loginUser.getUserId();
        recordDeviceLog(deviceObj.getId(), deviceObj.getDeviceName(), "更新语音", "更新语音", userId);
    }

    private String buildMqttTopic(String deviceImei) {
        String tenantId = LoginHelper.getTenantId();
        return MqttConstants.GLOBAL_PUB_KEY2 +tenantId + "/" + DEVICE_TYPE + deviceImei;
    }

    public void strobeMode(HBY100JStrobeModeDto params) {
        Device deviceObj = deviceMapper.selectById(params.getDeviceId());
        if (getDeviceStatus(deviceObj.getDeviceImei())) {
            throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
        }
        AppLoginUser loginUser = AppLoginHelper.getLoginUser();
        FuncType10StrobeModeRequest request = new FuncType10StrobeModeRequest();
        request.setRequestId(GenerateIdUtil.generateNumericId());
        request.setImei(deviceObj.getDeviceImei());
        request.setFuncType("10");
        request.setTimestamp(System.currentTimeMillis());
        FuncType10StrobeModeRequest.Data data = new FuncType10StrobeModeRequest.Data();
        data.setMode(params.getMode());
        data.setEnable(params.getEnable());
        request.setData(data);
        log.info("HBY100J爆闪模式开启/关闭，下发设备参数：{}", request);
        mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
        String content = params.getEnable() != null && params.getEnable() == 1 ? "爆闪模式开启" : "爆闪模式关闭";
        Long userId = loginUser == null ? pcUserId : loginUser.getUserId();
        recordDeviceLog(deviceObj.getId(), deviceObj.getDeviceName(), content, content, userId);
    }

    public void lightAdjustment(HBY100JLightAdjustmentDto params) {
        log.info("HBY100J灯光调节，请求参数：{}", params);
        Device deviceObj = deviceMapper.selectById(params.getDeviceId());
        if (deviceObj == null) {
            throw new ServiceException("设备不存在");
        }
        if (getDeviceStatus(deviceObj.getDeviceImei())) {
            throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
        }
        AppLoginUser loginUser = AppLoginHelper.getLoginUser();
        FuncType13BrightnessRequest request = new FuncType13BrightnessRequest();
        request.setRequestId(GenerateIdUtil.generateNumericId());
        request.setImei(deviceObj.getDeviceImei());
        request.setFuncType("13");
        request.setTimestamp(System.currentTimeMillis());
        FuncType13BrightnessRequest.Data data = new FuncType13BrightnessRequest.Data();
        data.setRed(params.getBrightness());
        data.setBlue(params.getBrightness());
        data.setYellow(params.getBrightness());
        request.setData(data);
        log.info("HBY100J灯光调节，下发设备参数：{}", request);
        mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
        Long userId = loginUser == null ? pcUserId : loginUser.getUserId();
        recordDeviceLog(deviceObj.getId(), deviceObj.getDeviceName(), "灯光调节", "灯光调节", userId);
    }

    public void strobeFrequency(HBY100JStrobeFrequencyDto params) {
        Device deviceObj = deviceMapper.selectById(params.getDeviceId());
        if (deviceObj == null) {
            throw new ServiceException("设备不存在");
        }
        if (getDeviceStatus(deviceObj.getDeviceImei())) {
            throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
        }
        AppLoginUser loginUser = AppLoginHelper.getLoginUser();
        FuncType11FrequencyRequest request = new FuncType11FrequencyRequest();
        request.setRequestId(GenerateIdUtil.generateNumericId());
        request.setImei(deviceObj.getDeviceImei());
        request.setFuncType("11");
        request.setTimestamp(System.currentTimeMillis());
        FuncType11FrequencyRequest.Data data = new FuncType11FrequencyRequest.Data();
        data.setFrequency(params.getFrequency());
        request.setData(data);
        log.info("HBY100J爆闪频率，下发设备参数：{}", request);
        mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
        Long userId = loginUser == null ? pcUserId : loginUser.getUserId();
        recordDeviceLog(deviceObj.getId(), deviceObj.getDeviceName(), "爆闪频率", "爆闪频率", userId);
    }

    public void updateVolume(HBY100JUpdateVolumeDto params) {
        Device deviceObj = deviceMapper.selectById(params.getDeviceId());
        if (deviceObj == null) {
            throw new ServiceException("设备不存在");
        }
        if (getDeviceStatus(deviceObj.getDeviceImei())) {
            throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
        }
        AppLoginUser loginUser = AppLoginHelper.getLoginUser();
        FuncType9UpdateVolumeRequest request = new FuncType9UpdateVolumeRequest();
        request.setRequestId(GenerateIdUtil.generateNumericId());
        request.setImei(deviceObj.getDeviceImei());
        request.setFuncType("9");
        request.setTimestamp(System.currentTimeMillis());
        FuncType9UpdateVolumeRequest.Data data = new FuncType9UpdateVolumeRequest.Data();
        data.setVolume(params.getVolume());
        request.setData(data);
        log.info("HBY100J更新音量，下发设备参数：{}", JSON.toJSONString(request));
        mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
        Long userId = loginUser == null ? pcUserId : loginUser.getUserId();
        recordDeviceLog(deviceObj.getId(), deviceObj.getDeviceName(), "更新音量", "更新音量", userId);
    }

    public void voiceBroadcast(HBY100JVoiceBroadcastDto params) {
        Device deviceObj = deviceMapper.selectById(params.getDeviceId());
        if (deviceObj == null) {
            throw new ServiceException("设备不存在");
        }
        if (getDeviceStatus(deviceObj.getDeviceImei())) {
            throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
        }
        AppLoginUser loginUser = AppLoginHelper.getLoginUser();
        FuncType6VoicePlayRequest request = new FuncType6VoicePlayRequest();
        request.setRequestId(GenerateIdUtil.generateNumericId());
        request.setImei(deviceObj.getDeviceImei());
        request.setFuncType("6");
        request.setTimestamp(System.currentTimeMillis());
        FuncType6VoicePlayRequest.Data data = new FuncType6VoicePlayRequest.Data();
        data.setVoiceBroadcast(params.getVoiceBroadcast());
        request.setData(data);
        log.info("HBY100J语音播报，下发设备参数：{}", request);
        mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
        Long userId = loginUser == null ? pcUserId : loginUser.getUserId();
        recordDeviceLog(deviceObj.getId(), deviceObj.getDeviceName(), "语音播报", "语音播报", userId);
    }


}
