package com.yida.data.server.service.impl;

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.crypto.SecureUtil;
import com.yida.data.common.core.entity.card.EduStudentCardLocation;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.device.dto.studentCard.CardMsgDTO;
import com.yida.data.rabbit.constant.RabbitConstant;
import com.yida.data.rabbit.util.RabbitUtil;
import com.yida.data.server.dto._810ABaseMsg;
import com.yida.data.server.dto._810ADeviceStaticDTO;
import com.yida.data.server.dto._810ALocationDTO;
import com.yida.data.server.dto._810ALowBatDTO;
import com.yida.data.server.dto._810ARiskAreaDTO;
import com.yida.data.server.dto._810AStepDTO;
import com.yida.data.server.repository.EduStudentCardLocationRespository;
import com.yida.data.server.service._810ADataService;
import com.yida.data.server.vo._810AResVO;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.Locale;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
@Slf4j
public class _810ADataServiceImpl implements _810ADataService {

    private final EduStudentCardLocationRespository eduStudentCardLocationRespository;
    private final RedisService redisService;
    private final RabbitUtil rabbitUtil;
    private final static Snowflake ID_GENERATOR = new Snowflake(1, 1);
    private final static String SECRET = "EDC9411E58C1D7B011A6DCE6985F0ACE";

    @Override
    public _810AResVO dealLocation(_810ALocationDTO dto) {
        log.info("接收定位数据:[{}],key:[{}]", dto, dto.getKEY());
        EduStudentCardLocation location = new EduStudentCardLocation();
        location.setId(ID_GENERATOR.nextId());
        location.setCreateDate(LocalDateTime.now());
        location.setType(dto.getTYPE());
        location.setLng(dto.getLO());
        location.setLat(dto.getLA());
        location.setImei(dto.getDEVICENUM());
        location.setBat(dto.getBAT());
        location.setGsm(dto.getGSM());
        location.setGps(dto.getGPS());
        location.setDeviceTime(dto.getLOCTIME());
        // 异或取反
        location.setOnline(dto.getISONLINE() ^ 1);
        if (location.getOnline() == 0) {
            redisService.set(CachePrefixConstant.DEVICE_CARD_ONLINE + location.getImei(), 0, 300L);
        }
        // 存入es
        eduStudentCardLocationRespository.save(location);
        // 消息通知
        CardMsgDTO reportMsg = new CardMsgDTO();
        BeanUtils.copyProperties(location, reportMsg);
        reportMsg.setAddress(dto.getPOSDESC());
        // 消息类型
        reportMsg.setMsgType(CardMsgDTO.LOCATION);
        rabbitUtil.convertAndSendMsg(RabbitConstant.CARD_EXCHANGE, RabbitConstant.CARD_810A_MSG_KEY, reportMsg);
        // 验签
        try {
//            this.signVerify(dto);
        } catch (Exception e) {
            log.error("验签失败,", e);
        }
        return null;
    }

    @Override
    public _810AResVO riskArea(_810ARiskAreaDTO dto) {
        log.info("接收危险区域数据:[{}],key:[{}]", dto, dto.getKEY());
        EduStudentCardLocation location = new EduStudentCardLocation();
        location.setId(ID_GENERATOR.nextId());
        location.setCreateDate(LocalDateTime.now());
        location.setType(dto.getTYPE());
        location.setLng(dto.getLO());
        location.setLat(dto.getLA());
        location.setImei(dto.getDEVICENUM());
        location.setBat(dto.getBAT());
        location.setGsm(dto.getGSM());
        location.setGps(dto.getGPS());
        location.setDeviceTime(dto.getLOCTIME());
        // 异或取反
        location.setOnline(0);
        if (location.getOnline() == 0) {
            redisService.set(CachePrefixConstant.DEVICE_CARD_ONLINE + location.getImei(), 0, 300L);
        }
        // 存入es
        eduStudentCardLocationRespository.save(location);
        // 消息通知
        CardMsgDTO reportMsg = new CardMsgDTO();
        BeanUtils.copyProperties(location, reportMsg);
        reportMsg.setAddress(dto.getPOSDESC());
        reportMsg.setRemark(dto.getREMARK());
        // 消息类型
        reportMsg.setMsgType(CardMsgDTO.RISK_AREA);
        rabbitUtil.convertAndSendMsg(RabbitConstant.CARD_EXCHANGE, RabbitConstant.CARD_810A_MSG_KEY, reportMsg);
        // 验签
        try {
//            this.signVerify(dto);
        } catch (Exception e) {
            log.error("验签失败,", e);
        }
        return null;
    }

    @Override
    public _810AResVO stepPush(_810AStepDTO dto) {
        log.info("接收步数:[{}],key:[{}]", dto, dto.getKEY());
        // 消息通知
        CardMsgDTO reportMsg = new CardMsgDTO();
        reportMsg.setStep(dto.getSTEPS());
        reportMsg.setImei(dto.getDEVICENUM());
        reportMsg.setDeviceTime(dto.getTIME());
        reportMsg.setMsgType(CardMsgDTO.STEP);
        rabbitUtil.convertAndSendMsg(RabbitConstant.CARD_EXCHANGE, RabbitConstant.CARD_810A_MSG_KEY, reportMsg);
        return null;
    }

    @Override
    public _810AResVO lowBat(_810ALowBatDTO dto) {
        log.info("接收低电量数据:[{}],key:[{}]", dto, dto.getKEY());
        EduStudentCardLocation location = new EduStudentCardLocation();
        location.setId(ID_GENERATOR.nextId());
        location.setCreateDate(LocalDateTime.now());
        location.setType(dto.getTYPE());
        location.setLng(dto.getLO());
        location.setLat(dto.getLA());
        location.setImei(dto.getDEVICENUM());
        location.setBat(dto.getBAT());
        location.setGsm(dto.getGSM());
        location.setGps(dto.getGPS());
        location.setDeviceTime(dto.getLOCTIME());
        // 异或取反
        location.setOnline(dto.getISONLINE() ^ 1);
        if (location.getOnline() == 0) {
            redisService.set(CachePrefixConstant.DEVICE_CARD_ONLINE + location.getImei(), 0, 300L);
        }
        // 存入es
        eduStudentCardLocationRespository.save(location);
        // 消息通知
        CardMsgDTO reportMsg = new CardMsgDTO();
        BeanUtils.copyProperties(location, reportMsg);
        reportMsg.setAddress(dto.getPOSDESC());
        // 消息类型
        reportMsg.setMsgType(CardMsgDTO.LOW_BAT);
        rabbitUtil.convertAndSendMsg(RabbitConstant.CARD_EXCHANGE, RabbitConstant.CARD_810A_MSG_KEY, reportMsg);
        // 验签
        try {
//            this.signVerify(dto);
        } catch (Exception e) {
            log.error("验签失败,", e);
        }
        return null;
    }

    @Override
    public _810AResVO deviceStatic(_810ADeviceStaticDTO dto) {
        log.info("接收设备脱落数据:[{}],key:[{}]", dto, dto.getKEY());
        EduStudentCardLocation location = new EduStudentCardLocation();
        location.setId(ID_GENERATOR.nextId());
        location.setCreateDate(LocalDateTime.now());
        location.setType(dto.getTYPE());
        location.setLng(dto.getLO());
        location.setLat(dto.getLA());
        location.setImei(dto.getDEVICENUM());
        location.setBat(dto.getBAT());
        location.setGsm(dto.getGSM());
        location.setGps(dto.getGPS());
        location.setDeviceTime(dto.getLOCTIME());
        // 异或取反
        location.setOnline(dto.getISONLINE() ^ 1);
        if (location.getOnline() == 0) {
            redisService.set(CachePrefixConstant.DEVICE_CARD_ONLINE + location.getImei(), 0, 300L);
        }
        // 存入es
        eduStudentCardLocationRespository.save(location);
        // 消息通知
        CardMsgDTO reportMsg = new CardMsgDTO();
        BeanUtils.copyProperties(location, reportMsg);
        reportMsg.setAddress(dto.getPOSDESC());
        // 消息类型
        reportMsg.setMsgType(CardMsgDTO.DEVICE_STATIC);
        rabbitUtil.convertAndSendMsg(RabbitConstant.CARD_EXCHANGE, RabbitConstant.CARD_810A_MSG_KEY, reportMsg);
        // 验签
        try {
//            this.signVerify(dto);
        } catch (Exception e) {
            log.error("验签失败,", e);
        }
        return null;
    }

    private void signVerify(_810ABaseMsg param) {
        StringBuilder builder = new StringBuilder().append(SECRET).append(param.getTIMESTAMP());
        Class<?> targetClass = param.getClass();
        Field[] fields = targetClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                builder.append(field.getName())
                    .append("=")
                    .append(field.getType().equals(LocalDateTime.class) ? LocalDateTimeUtil
                        .format((LocalDateTime) field.get(param), "yyyy-MM-dd HH:mm:ss") : String.valueOf(field.get(param)));
            } catch (Exception e) {
                log.error("810A验签失败", e);
            }
        }
        log.info("验签字符串:[{}]", builder);
        String sign = SecureUtil.md5().digestHex(builder.toString()).toUpperCase(Locale.ROOT);
        log.info("计算出的sign:[{}]", sign);
        log.info("接收的sign:[{}]", param.getSIGN());
    }
}
