package com.yuchen.saas.park.service.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuchen.saas.message.api.dto.WebSocketMessagDTO;
import com.yuchen.saas.message.api.feign.ws.WebSocketFeignServer;
import com.yuchen.saas.park.api.dto.prevention.ScanPageQueryDTO;
import com.yuchen.saas.park.api.dto.prevention.ScanPreventionDTO;
import com.yuchen.saas.park.api.entity.device.PmgBatSmartEquipment;
import com.yuchen.saas.park.api.entity.park.PmgBatParkInfo;
import com.yuchen.saas.park.api.entity.park.ScanPrevention;
import com.yuchen.saas.park.api.enums.AcidAssayResultEnum;
import com.yuchen.saas.park.api.enums.HealthCodeEnum;
import com.yuchen.saas.park.api.enums.PassEnum;
import com.yuchen.saas.park.api.request.ScanPageQueryRequest;
import com.yuchen.saas.park.api.response.ScanPreventionResponse;
import com.yuchen.saas.park.api.response.ScanPreventionStaticsResponse;
import com.yuchen.saas.park.api.vo.park.prevention.*;
import com.yuchen.saas.park.service.constant.TorchConstant;
import com.yuchen.saas.park.service.mapper.ScanPreventionMapper;
import com.yuchen.saas.park.service.service.PmgBatParkInfoService;
import com.yuchen.saas.park.service.service.PmgBatSmartEquipmentService;
import com.yuchen.saas.park.service.service.ScanPreventionService;
import com.yuchen.saas.park.service.util.DateTimeUtils;
import com.yuchen.saas.park.service.wrapper.ScanPreventionWrapper;
import com.yuchen.saas.parking.api.util.DateUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.nest.springwrap.core.mp.base.BaseServiceImpl;
import org.nest.springwrap.core.mp.support.Condition;
import org.nest.springwrap.core.mp.support.Query;
import org.nest.springwrap.core.secure.utils.AuthUtil;
import org.nest.springwrap.core.tool.api.R;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 颜艺波
 * @date 2022/6/16 16:19
 * @Description
 */
@Service
public class ScanPreventionServiceImpl extends BaseServiceImpl<ScanPreventionMapper, ScanPrevention>
        implements ScanPreventionService {

    @Resource
    //SimpMessagingTemplate simpMessagingTemplate;
    private WebSocketFeignServer webSocketClient;

    @Autowired
    PmgBatSmartEquipmentService equipmentService;

  /*  *//**
     * 设备服务指令下发服务
     *//*
    @Autowired
    IoTCallService ioTCallService;*/
    @Resource
    private PmgBatParkInfoService pmgBatParkInfoService;

    @Override
    public boolean add(ScanPreventionDTO scanPreventionDTO) {
        scanPreventionDTO.setScanTime(System.currentTimeMillis());
        ScanPrevention scanPrevention = new ScanPrevention();
        BeanUtils.copyProperties(scanPreventionDTO, scanPrevention);
        // 园区id通过设备查询数据库获取
        PmgBatSmartEquipment equipment = equipmentService.getOne(Wrappers.<PmgBatSmartEquipment>lambdaQuery()
                .select(PmgBatSmartEquipment::getParkId)
                .eq(PmgBatSmartEquipment::getProductKey, scanPreventionDTO.getProductKey())
                .eq(PmgBatSmartEquipment::getDeviceName, scanPreventionDTO.getDeviceName()));
        if (equipment != null) {
            scanPrevention.setParkId(equipment.getParkId());
            scanPrevention.setTenantId("108994");
            System.out.println("11111111"+equipment.getTenantId());
        } else {
            scanPrevention.setParkId(34325345354L);
            System.out.println("2222=="+34325345354L);
        }
        if (HealthCodeEnum.GREEN.getCode().equals(scanPrevention.getHealthCodeStatus())
                && AcidAssayResultEnum.NEGATIVE.getCode().equals(scanPrevention.getNucleicAcidAssayResult())) {
            // 通行
            scanPrevention.setPassStatus(PassEnum.PASS.getCode());
        } else {
            // 禁止通行
            scanPrevention.setPassStatus(PassEnum.FORBIDDEN.getCode());
        }

        this.save(scanPrevention);

       /* // 通行指令
        CallingDeviceServiceRequest passRequest = new CallingDeviceServiceRequest();
        passRequest.setProductKey(scanPrevention.getProductKey());
        passRequest.setDeviceName(scanPrevention.getDeviceName());
        passRequest.setIdentifier("issue_pass_command");
        // 语音播报
        CallingDeviceServiceRequest voiceRequest = new CallingDeviceServiceRequest();
        voiceRequest.setProductKey(scanPrevention.getProductKey());
        voiceRequest.setDeviceName(scanPrevention.getDeviceName());
        voiceRequest.setIdentifier("voice_broadcast");
        if (PassEnum.PASS.getCode().equals(scanPrevention.getPassStatus())) {
            passRequest.addParam("isPass", "1");
            ioTCallService.deviceServiceCall(passRequest);
            voiceRequest.addParam("content", "请通行");
            ioTCallService.deviceServiceCall(voiceRequest);
        } else {
            passRequest.addParam("isPass", "0");
            ioTCallService.deviceServiceCall(passRequest);
            voiceRequest.addParam("content", "禁止通行");
            ioTCallService.deviceServiceCall(voiceRequest);
        }*/
        // webSocket推送前端
        //simpMessagingTemplate.convertAndSendToUser(String.valueOf(scanPrevention.getParkId()),"/iscScanPrevention/latestData", new ScanPreventionWrapper().entityVO(scanPrevention));

        WebSocketMessagDTO dto = new WebSocketMessagDTO(String.valueOf(scanPrevention.getParkId()),
                "/iscScanPrevention/latestData", BeanUtil.beanToMap(scanPrevention));
        webSocketClient.convertAndSendToUser(dto);
        return true;
    }

    @Override
    public List<ScanPreventionVO> latestDataQuery(Long parkId) {
        LambdaQueryWrapper<ScanPrevention> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ScanPrevention::getParkId, parkId)
                .orderByDesc(ScanPrevention::getScanTime).last("limit 8");
        List<ScanPrevention> scanPreventionList = this.list(queryWrapper);
        return new ScanPreventionWrapper().listVO(scanPreventionList);
    }

    @Override
    public IPage<ScanPreventionVO> pageQuery(ScanPageQueryDTO scanPageQueryDTO, Query query) {
        LambdaQueryWrapper<ScanPrevention> pageQueryWrapper = new LambdaQueryWrapper<>();
        pageQueryWrapper.eq(ScanPrevention::getParkId, scanPageQueryDTO.getParkId())
                .eq(ObjectUtils.isNotEmpty(scanPageQueryDTO.getHealthCodeStatus()),
                        ScanPrevention::getHealthCodeStatus, scanPageQueryDTO.getHealthCodeStatus())
                .eq(ObjectUtils.isNotEmpty(scanPageQueryDTO.getInjectionTime()),
                        ScanPrevention::getInjectionTime, scanPageQueryDTO.getInjectionTime())
                .ge(ObjectUtils.isNotEmpty(scanPageQueryDTO.getBeginTime()),
                        ScanPrevention::getScanTime,
                        DateTimeUtils.dateTimeToTimestamp(scanPageQueryDTO.getBeginTime()))
                .le(ObjectUtils.isNotEmpty(scanPageQueryDTO.getEndTime()),
                        ScanPrevention::getScanTime,
                        DateTimeUtils.dateTimeToTimestamp(scanPageQueryDTO.getEndTime()))
                .orderByDesc(ScanPrevention::getScanTime);
        IPage<ScanPrevention> scanPreventionPage = this.page(Condition.getPage(query), pageQueryWrapper);
        ScanPreventionWrapper scanPreventionWrapper = new ScanPreventionWrapper();
        IPage<ScanPreventionVO> pageVO = scanPreventionWrapper.pageVO(scanPreventionPage);
        // 获取设备名称
        for (ScanPreventionVO scanPreventionVO : pageVO.getRecords()) {
            PmgBatSmartEquipment equipment = equipmentService.getOne(Wrappers.<PmgBatSmartEquipment>lambdaQuery()
                    .select(PmgBatSmartEquipment::getName)
                    .eq(PmgBatSmartEquipment::getProductKey, scanPreventionVO.getProductKey())
                    .eq(PmgBatSmartEquipment::getDeviceName, scanPreventionVO.getDeviceName()));
            if (equipment != null) {
                scanPreventionVO.setDeviceAliasName(equipment.getName());
            } else {
                scanPreventionVO.setDeviceAliasName("枪机监控点-艾德双目人脸识别相机");
            }
        }
        return pageVO;
    }

    @Override
    public HealthCodeTodayVO healthCodeToday(Long parkId) {
        List<ScanPrevention> list = this.list(Wrappers.<ScanPrevention>lambdaQuery()
                .eq(ScanPrevention::getParkId, parkId)
                .ge(ScanPrevention::getScanTime, DateTimeUtils.beginTimestampToday())
                .le(ScanPrevention::getScanTime, DateTimeUtils.endTimestampToday()));
        HealthCodeTodayVO healthCodeTodayVO = new HealthCodeTodayVO();
        healthCodeTodayVO.setGreenCount((int)list.stream().filter(temp -> HealthCodeEnum.GREEN.getCode()
                .equals(temp.getHealthCodeStatus())).count());
        healthCodeTodayVO.setYellowCount((int)list.stream().filter(temp -> HealthCodeEnum.YELLOW.getCode()
                .equals(temp.getHealthCodeStatus())).count());
        healthCodeTodayVO.setRedCount((int)list.stream().filter(temp -> HealthCodeEnum.RED.getCode()
                .equals(temp.getHealthCodeStatus())).count());
        healthCodeTodayVO.setOtherCount((int)list.stream().filter(temp -> HealthCodeEnum.OTHER.getCode()
                .equals(temp.getHealthCodeStatus())).count());
        return healthCodeTodayVO;
    }

    @Override
    public TemperatureTodayVO temperatureToday(Long parkId) {
        List<ScanPrevention> list = this.list(Wrappers.<ScanPrevention>lambdaQuery()
                .eq(ScanPrevention::getParkId, parkId)
                .ge(ScanPrevention::getScanTime, DateTimeUtils.beginTimestampToday())
                .le(ScanPrevention::getScanTime, DateTimeUtils.endTimestampToday()));
        TemperatureTodayVO temperatureTodayVO = new TemperatureTodayVO();
        temperatureTodayVO.setAbnormalCount((int)list.stream().filter(temp -> temp.getTemperature() > Float.parseFloat(
                TorchConstant.TEMPERATURE)).count());
        temperatureTodayVO.setNormalCount((int)list.stream().filter(temp -> temp.getTemperature() <= Float.parseFloat(TorchConstant.TEMPERATURE)).count());
        return temperatureTodayVO;
    }

    @Override
    public List<CoordinateVO> vaccineStatisticsToday(Long parkId) {
        List<ScanPrevention> list = this.list(Wrappers.<ScanPrevention>lambdaQuery()
                .eq(ScanPrevention::getParkId, parkId)
                .ge(ScanPrevention::getScanTime, DateTimeUtils.beginTimestampToday())
                .le(ScanPrevention::getScanTime, DateTimeUtils.endTimestampToday()));
        Map<Integer, List<ScanPrevention>> map =
                list.stream().collect(Collectors.groupingBy(ScanPrevention::getInjectionTime));
        List<CoordinateVO> statisticList = new ArrayList<>();
        for (Map.Entry<Integer, List<ScanPrevention>> entry : map.entrySet()) {
            statisticList.add(new CoordinateVO(String.valueOf(entry.getKey()), String.valueOf(entry.getValue().size())));
        }
        return statisticList.stream().sorted(Comparator.comparing(CoordinateVO::getKey)).collect(Collectors.toList());
    }

    @Override
    public PreventionStatisticVO preventionStatistic(Long parkId) {
        //本月
        int countMonth = this.count(Wrappers.<ScanPrevention>lambdaQuery()
                .eq(ScanPrevention::getParkId, parkId)
                .ge(ScanPrevention::getScanTime, DateTimeUtils.beginTimestampMonth())
                .le(ScanPrevention::getScanTime, System.currentTimeMillis()));
        //上月
        int countLastMonth = this.count(Wrappers.<ScanPrevention>lambdaQuery()
                .eq(ScanPrevention::getParkId, parkId)
                .ge(ScanPrevention::getScanTime, DateTimeUtils.beginTimestampLastMonth())
                .le(ScanPrevention::getScanTime, DateTimeUtils.endTimestampLastMonth()));
        PreventionStatisticVO preventionStatisticVO = new PreventionStatisticVO();
        preventionStatisticVO.setThisMonth(countMonth);
        preventionStatisticVO.setLastMonth(countLastMonth);
        return preventionStatisticVO;
    }

    @Override
    public R<IPage<ScanPreventionResponse>> listPage(ScanPageQueryRequest scanPageQueryRequest, Query query) {
        //分页查询
        PmgBatParkInfo pmgBatParkInfo =   pmgBatParkInfoService.lambdaQuery().select(PmgBatParkInfo::getId).one();
        IPage<ScanPreventionResponse> iPage = new Page<>(query.getCurrent(),query.getSize());
        String tenantId= AuthUtil.getUser().getTenantId();
        if(StringUtils.isNotBlank(scanPageQueryRequest.getStartTime())){
            scanPageQueryRequest.setStartTime(DateUtils.DateTimeOfStrToLong(scanPageQueryRequest.getStartTime()).toString());
            scanPageQueryRequest.setEndTime(DateUtils.DateTimeOfStrToLong(scanPageQueryRequest.getEndTime()).toString());
        }
        IPage<ScanPreventionResponse> pageVo = baseMapper.listPage(iPage,scanPageQueryRequest,tenantId,pmgBatParkInfo.getId());
        return R.data(pageVo);
    }

    @Override
    public HealthCodeTodayVO healthCodeHistory(Long parkId) {
        PmgBatParkInfo pmgBatParkInfo =   pmgBatParkInfoService.lambdaQuery().select(PmgBatParkInfo::getId).one();
        if(Objects.isNull(parkId)){
            parkId = pmgBatParkInfo.getId();
        }
        List<ScanPreventionStaticsResponse> list = baseMapper.historyScanPreventionStatics(Long.valueOf(AuthUtil.getUser().getTenantId()),pmgBatParkInfo.getId());
        HealthCodeTodayVO healthCodeTodayVO = new HealthCodeTodayVO();
        int total = 0;
        for (ScanPreventionStaticsResponse scanPreventionStaticsResponse : list) {
            if(scanPreventionStaticsResponse.getStatus().equals(HealthCodeEnum.GREEN.getCode())){
                healthCodeTodayVO.setGreenCount(scanPreventionStaticsResponse.getCount());
            }
            if(scanPreventionStaticsResponse.getStatus().equals(HealthCodeEnum.YELLOW.getCode())){
                healthCodeTodayVO.setYellowCount(scanPreventionStaticsResponse.getCount());
            }
            if(scanPreventionStaticsResponse.getStatus().equals(HealthCodeEnum.RED.getCode())){
                healthCodeTodayVO.setRedCount(scanPreventionStaticsResponse.getCount());
            }
            if(scanPreventionStaticsResponse.getStatus().equals(HealthCodeEnum.OTHER.getCode())){
                healthCodeTodayVO.setOtherCount(scanPreventionStaticsResponse.getCount());
            }
                total += scanPreventionStaticsResponse.getCount();
        }
        healthCodeTodayVO.setTotalCount(total);
        return healthCodeTodayVO;
    }
}
