package com.fuyuanshen.app.service;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fuyuanshen.app.domain.AppPersonnelInfo;
import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo;
import com.fuyuanshen.app.domain.dto.APPReNameDTO;
import com.fuyuanshen.app.domain.vo.APPDeviceTypeVo;
import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo;
import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper;
import com.fuyuanshen.app.mapper.equipment.APPDeviceMapper;
import com.fuyuanshen.common.core.exception.ServiceException;
import com.fuyuanshen.common.core.utils.MapstructUtils;
import com.fuyuanshen.common.core.utils.ObjectUtils;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.domain.dto.AppDeviceBo;
import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo;
import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria;
import com.fuyuanshen.equipment.domain.vo.AppDeviceVo;
import com.fuyuanshen.equipment.enums.BindingStatusEnum;
import com.fuyuanshen.equipment.enums.CommunicationModeEnum;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
import com.fuyuanshen.equipment.utils.c.ReliableTextToBitmap;
import com.fuyuanshen.system.mqtt.config.MqttGateway;
import com.fuyuanshen.system.mqtt.constants.MqttConstants;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Slf4j
@Service
@RequiredArgsConstructor
public class AppDeviceBizService {

    private final APPDeviceMapper appDeviceMapper;
    private final DeviceMapper deviceMapper;
    private final AppPersonnelInfoMapper appPersonnelInfoMapper;
    private final DeviceTypeMapper deviceTypeMapper;
    private final MqttGateway mqttGateway;


    public List<APPDeviceTypeVo> getTypeList() {
        Long userId = AppLoginHelper.getUserId();
        return appDeviceMapper.getTypeList(userId);
    }

    public void reName(APPReNameDTO reNameDTO) {
        UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", reNameDTO.getId())
                .eq("binding_user_id", AppLoginHelper.getUserId())
                .set("device_name", reNameDTO.getDeviceName());
        deviceMapper.update(updateWrapper);
    }


    public int sendMessage(AppDeviceSendMsgBo bo) {
        List<Long> deviceIds = bo.getDeviceIds();
        if(deviceIds == null || deviceIds.isEmpty()){
            throw new ServiceException("请选择设备");
        }
        for (Long deviceId : deviceIds){
            Device deviceObj = deviceMapper.selectById(deviceId);
            if(deviceObj==null) {
                throw new ServiceException("设备不存在"+deviceId);
            }

            byte[] msg = ReliableTextToBitmap.textToBitmapBytes(bo.getSendMsg());
            Map<String,Object> linkHashMap = new HashMap<>();
            linkHashMap.put("message",msg);
            String sendMsg = JSON.toJSONString(linkHashMap);
            mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+deviceObj.getDeviceImei(), 1 ,sendMsg);
            log.info("发送设备消息：{}", bo.getSendMsg());

            UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", deviceId)
                    .eq("binding_user_id", AppLoginHelper.getUserId())
                    .set("send_msg", bo.getSendMsg());
            deviceMapper.update(updateWrapper);
        }
        return 1;
    }


    public TableDataInfo<AppDeviceVo> queryAppDeviceList(DeviceQueryCriteria bo, PageQuery pageQuery) {
        if (bo.getBindingUserId() == null) {
            Long userId = AppLoginHelper.getUserId();
            bo.setBindingUserId(userId);
        }
        Page<AppDeviceVo> result = deviceMapper.queryAppBindDeviceList(pageQuery.build(), bo);
        return TableDataInfo.build(result);
    }

    public int bindDevice(AppDeviceBo bo) {
        Integer mode = bo.getCommunicationMode();
        Long userId = AppLoginHelper.getUserId();
        if (mode == CommunicationModeEnum.FOUR_G.getValue()) {

            String deviceImei = bo.getDeviceImei();
            QueryWrapper<Device> qw = new QueryWrapper<Device>()
                    .eq("device_imei", deviceImei);
            List<Device> devices = deviceMapper.selectList(qw);
            if (devices.isEmpty()) {
                throw new RuntimeException("请先将设备入库！！！");
            }
            Device device = devices.get(0);
            if (device.getBindingStatus() != null && device.getBindingStatus() == BindingStatusEnum.BOUND.getCode()) {
                throw new RuntimeException("设备已绑定");
            }
            UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
            deviceUpdateWrapper.eq("id", device.getId())
                    .set("binding_status", BindingStatusEnum.BOUND.getCode())
                    .set("binding_user_id", userId)
                    .set("binding_time", new Date());


            return deviceMapper.update(null, deviceUpdateWrapper);
        } else if (mode == CommunicationModeEnum.BLUETOOTH.getValue()) {
            String deviceMac = bo.getDeviceMac();
            QueryWrapper<Device> qw = new QueryWrapper<Device>()
                    .eq("device_mac", deviceMac);
            List<Device> devices = deviceMapper.selectList(qw);
            if (devices.isEmpty()) {
                throw new RuntimeException("请先将设备入库！！！");
            }
            Device device = devices.get(0);
            if (device.getBindingStatus() != null && device.getBindingStatus() == BindingStatusEnum.BOUND.getCode()) {
                throw new RuntimeException("设备已绑定");
            }
            UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
            deviceUpdateWrapper.eq("id", device.getId())
                    .set("binding_status", BindingStatusEnum.BOUND.getCode())
                    .set("binding_user_id", userId)
                    .set("binding_time", new Date());
            return deviceMapper.update(null, deviceUpdateWrapper);
        } else {
            throw new RuntimeException("通讯方式错误");
        }

    }

    public int unBindDevice(Long id) {
        Device device = deviceMapper.selectById(id);
        if (device == null) {
            throw new RuntimeException("请先将设备入库！！！");
        }
        UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
        deviceUpdateWrapper.eq("id", device.getId())
                .set("binding_status", BindingStatusEnum.UNBOUND.getCode())
                .set("binding_user_id", null)
                .set("binding_time", null);
        return deviceMapper.update(null, deviceUpdateWrapper);
    }

    public AppDeviceDetailVo getInfo(Long id) {
        Device device = deviceMapper.selectById(id);
        if (device == null) {
            throw new RuntimeException("请先将设备入库！！！");
        }
        AppDeviceDetailVo vo = new AppDeviceDetailVo();
        vo.setDeviceId(device.getId());
        vo.setDeviceName(device.getDeviceName());
        vo.setDevicePic(device.getDevicePic());
        vo.setDeviceImei(device.getDeviceImei());
        vo.setDeviceMac(device.getDeviceMac());
        vo.setDeviceStatus(device.getDeviceStatus());
        DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
        if(deviceType!=null){
            vo.setCommunicationMode(Integer.valueOf(deviceType.getCommunicationMode()));
            vo.setTypeName(deviceType.getTypeName());
        }
        vo.setBluetoothName(device.getBluetoothName());

        vo.setSendMsg(device.getSendMsg());

        QueryWrapper<AppPersonnelInfo> qw = new QueryWrapper<AppPersonnelInfo>()
                .eq("device_id", device.getId());
        AppPersonnelInfo appPersonnelInfo = appPersonnelInfoMapper.selectOne(qw);
        if(appPersonnelInfo != null){
            AppPersonnelInfoVo personnelInfoVo = MapstructUtils.convert(appPersonnelInfo, AppPersonnelInfoVo.class);
            vo.setPersonnelInfo(personnelInfoVo);
        }
        return vo;
    }

    public boolean registerPersonInfo(AppPersonnelInfoBo bo) {
        Long deviceId = bo.getDeviceId();
        Device deviceObj = deviceMapper.selectById(deviceId);
        if(deviceObj == null){
            throw new RuntimeException("请先将设备入库！！！");
        }
        QueryWrapper<AppPersonnelInfo> qw = new QueryWrapper<AppPersonnelInfo>()
                .eq("device_id", deviceId);
        List<AppPersonnelInfoVo> appPersonnelInfoVos = appPersonnelInfoMapper.selectVoList(qw);
//        unitName,position,name,id
        byte[] unitName = ReliableTextToBitmap.textToBitmapBytes(bo.getUnitName());
        byte[] position = ReliableTextToBitmap.textToBitmapBytes(bo.getPosition());
        byte[] name = ReliableTextToBitmap.textToBitmapBytes(bo.getName());
        byte[] id = ReliableTextToBitmap.textToBitmapBytes(bo.getCode());
        Map<String,Object> linkHashMap = new HashMap<>();
        linkHashMap.put("unitName",unitName);
        linkHashMap.put("position",position);
        linkHashMap.put("name",name);
        linkHashMap.put("id",id);
        String personnelInfo = JSON.toJSONString(linkHashMap);
        mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+deviceObj.getDeviceImei(), 1 ,personnelInfo);
        log.info("发送点阵数据到设备消息：{}", bo);

        if(ObjectUtils.length(appPersonnelInfoVos) == 0){
            AppPersonnelInfo appPersonnelInfo = MapstructUtils.convert(bo, AppPersonnelInfo.class);
            return appPersonnelInfoMapper.insertOrUpdate(appPersonnelInfo);
        }else {
            UpdateWrapper<AppPersonnelInfo> uw = new UpdateWrapper<>();
            uw.eq("device_id", deviceId)
                    .set("name", bo.getName())
                    .set("position", bo.getPosition())
                    .set("unit_name", bo.getUnitName())
                    .set("code",bo.getCode());
            return appPersonnelInfoMapper.update(null, uw)>0;
        }


    }
}
