package com.usky.park.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.usky.common.core.bean.CommonPage;
import com.usky.common.security.utils.SecurityUtils;
import com.usky.park.domain.*;
import com.usky.park.service.DataEvHistoryService;
import com.usky.park.service.DataGrHistoryService;
import com.usky.park.service.DataLgHistoryService;
import com.usky.park.mapper.DmpDeviceMapper;
import com.usky.park.service.*;
import com.usky.common.mybatis.core.AbstractCrudService;
import com.usky.park.service.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 设备信息表 服务实现类
 * </p>
 *
 * @author zyj
 * @since 2023-03-30
 */
@Service
public class DmpDeviceServiceImpl extends AbstractCrudService<DmpDeviceMapper, DmpDevice> implements DmpDeviceService {
    @Autowired
    private DataRealTimeService dataRealTimeService;

    @Autowired
    private DataGrHistoryService dataGrHistoryService;

    @Autowired
    private DataEvHistoryService dataEvHistoryService;

    @Autowired
    private DataLgHistoryService dataLgHistoryService;

    @Override
    public CommonPage<DmpDeviceVO> dmpDeviceList(String deviceName,String installAddress,Integer deviceType,String deviceStatus,String doorStatus,String switchStatus,String startDate,String endDate,Integer pageNum,Integer pageSize){

        LambdaQueryWrapper<DmpDevice> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(DmpDevice::getDeviceId,DmpDevice::getDeviceCode,DmpDevice::getDeviceName,DmpDevice::getDeviceType,DmpDevice::getInstallAddress,DmpDevice::getCreatedTime,DmpDevice::getUpdatedTime)
                .eq(DmpDevice::getDeviceType,deviceType)
                .eq(DmpDevice::getDeleteFlag,0)
                .like(StringUtils.isNotBlank(deviceName),DmpDevice::getDeviceName,deviceName)
                .like(StringUtils.isNotBlank(installAddress),DmpDevice::getInstallAddress,installAddress)
                .between(StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate),DmpDevice::getCreatedTime,startDate,endDate)
                .orderByDesc(DmpDevice::getId);
        List<DmpDevice> pagelist = this.list(queryWrapper);
        List<DmpDeviceVO> list = new ArrayList<>();
        if(pagelist.size()>0){
            List<String> deviceIdList = new ArrayList<>();
            for(int i=0;i<pagelist.size();i++){
                deviceIdList.add(pagelist.get(i).getDeviceId());
            }

            List<DataRealTime> list1 = new ArrayList<>();
            LambdaQueryWrapper<DataRealTime> queryWrapper1 = Wrappers.lambdaQuery();
            queryWrapper1.select(DataRealTime::getDeviceId,DataRealTime::getAttributeName,DataRealTime::getAttributeData)
                    .eq(DataRealTime::getAttributeName,"device_status")
                    .in(DataRealTime::getDeviceId,deviceIdList);
            list1 = dataRealTimeService.list(queryWrapper1);

            List<DataRealTime> list2 = new ArrayList<>();
            LambdaQueryWrapper<DataRealTime> queryWrapper2 = Wrappers.lambdaQuery();
            queryWrapper2.select(DataRealTime::getDeviceId,DataRealTime::getAttributeName,DataRealTime::getAttributeData)
                    .eq(DataRealTime::getAttributeName,"door_status")
                    .in(DataRealTime::getDeviceId,deviceIdList);
            list2 = dataRealTimeService.list(queryWrapper2);


            List<DataRealTime> switchList = new ArrayList<>();
            LambdaQueryWrapper<DataRealTime> queryWrapper3 = Wrappers.lambdaQuery();
            queryWrapper3.select(DataRealTime::getDeviceId,DataRealTime::getAttributeName,DataRealTime::getAttributeData)
                    .eq(DataRealTime::getAttributeName,"switch_status")
                    .in(DataRealTime::getDeviceId,deviceIdList);
            switchList = dataRealTimeService.list(queryWrapper3);


            List<DmpDeviceVO> list3 = new ArrayList<>();
            for(int i=0;i<pagelist.size();i++){

                DmpDeviceVO dmpDeviceVO = new DmpDeviceVO();
                dmpDeviceVO.setDeviceId(pagelist.get(i).getDeviceId());
                dmpDeviceVO.setDeviceCode(pagelist.get(i).getDeviceCode());
                dmpDeviceVO.setDeviceName(pagelist.get(i).getDeviceName());
                dmpDeviceVO.setInstallAddress(pagelist.get(i).getInstallAddress());
                dmpDeviceVO.setCreatedTime((pagelist.get(i).getCreatedTime()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                if(pagelist.get(i).getUpdatedTime() != null){
                    dmpDeviceVO.setUpdateTime((pagelist.get(i).getUpdatedTime()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

                }


                if(list1.size()>0){
                    for(int j=0;j<list1.size();j++){
                        if(pagelist.get(i).getDeviceId().equals(list1.get(j).getDeviceId())){
                            dmpDeviceVO.setDeviceStatus(list1.get(j).getAttributeData());
                        }
                    }
                }

                if(list2.size()>0){
                    for(int j=0;j<list2.size();j++){
                        if(pagelist.get(i).getDeviceId().equals(list2.get(j).getDeviceId())){
                            dmpDeviceVO.setDoorStatus(list2.get(j).getAttributeData());
                        }
                    }
                }

                if(switchList.size()>0){
                    for(int j=0;j<switchList.size();j++){
                        if(pagelist.get(i).getDeviceId().equals(switchList.get(j).getDeviceId())){
                            dmpDeviceVO.setSwitchStatus(switchList.get(j).getAttributeData());
                        }
                    }
                }
                list3.add(dmpDeviceVO);
            }

            if(StringUtils.isNotBlank(deviceStatus)){
                list3 = list3.stream().filter(e -> deviceStatus.equals(e.getDeviceStatus())).collect(Collectors.toList());
            }

            if(StringUtils.isNotBlank(doorStatus)){
                list3 = list3.stream().filter(e -> doorStatus.equals(e.getDoorStatus())).collect(Collectors.toList());
            }

            if(StringUtils.isNotBlank(switchStatus)){
                list3 = list3.stream().filter(e -> switchStatus.equals(e.getSwitchStatus())).collect(Collectors.toList());
            }

            if(list3.size()>0){
                for(int i=0;i<list3.size();i++){
                    list.add(list3.get(i));
                }
            }

        }
        int total=0;
        if(list.size()>0){
            total = list.size();
        }
        int current = 0;
        if (pageNum != null && pageSize > 0) {
            current = (pageNum - 1) * pageSize;
        }
        List<DmpDeviceVO> list4 = list.stream().skip(current).limit(pageSize).collect(Collectors.toList());

        return new CommonPage<>(list4,total,pageNum,pageSize);

    }

    @Override
    public CommonPage<Object> deviceCurrentDataList(String deviceName,String installAddress,Integer deviceType,Integer switchStatus,Integer pageNum,Integer pageSize){
        List<Object> list = new ArrayList<>();

        List<DmpDevice> devList = new ArrayList<>();
        LambdaQueryWrapper<DmpDevice> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(DmpDevice::getDeviceId,DmpDevice::getDeviceName,DmpDevice::getInstallAddress)
                .eq(DmpDevice::getDeleteFlag,0)
                .like(StringUtils.isNotBlank(deviceName),DmpDevice::getDeviceName,deviceName)
                .like(StringUtils.isNotBlank(installAddress),DmpDevice::getInstallAddress,installAddress)
                .eq(DmpDevice::getDeviceType,deviceType);
        devList = this.list(queryWrapper);

        if(devList.size() <=0){
            return new CommonPage<>(list,0,pageNum,pageSize);
        }

        if(devList.size()>0){
            for(int i=0;i<devList.size();i++){
                Map<String,Object> map = new HashMap<>();
                map.put("deviceId",devList.get(i).getDeviceId());
                map.put("deviceName",devList.get(i).getDeviceName());
                map.put("installAddress",devList.get(i).getInstallAddress());
                map.put("latestTime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

                List<DataRealTime> dataRealList = new ArrayList<>();
                LambdaQueryWrapper<DataRealTime> queryWrapper1 = Wrappers.lambdaQuery();
                queryWrapper1.select(DataRealTime::getAttributeName,DataRealTime::getAttributeData,DataRealTime::getDataTime)
                        .eq(DataRealTime::getDeviceId,devList.get(i).getDeviceId());
                dataRealList = dataRealTimeService.list(queryWrapper1);
                if(dataRealList.size()>0){
                    Boolean found = true;
                    boolean exist = false;
                    for(int j=0;j<dataRealList.size();j++){
                        map.put(dataRealList.get(j).getAttributeName(),dataRealList.get(j).getAttributeData());
                        map.put(dataRealList.get(j).getAttributeName()+"Time",dataRealList.get(j).getDataTime());
                        if((deviceType == 510) && (switchStatus != null)){
                            if((("switch_status").equals(dataRealList.get(j).getAttributeName())) && (switchStatus != Integer.valueOf(dataRealList.get(j).getAttributeData()))){
                                found = false;
                            }
                        }
                        if(dataRealList.get(j).getAttributeData().equals("-50")){
                            exist = true;
                        }
                    }
                    if(!exist){
                        if(deviceType == 510){
                            if(found){
                                list.add(map);
                            }
                        }else{
                            list.add(map);
                        }
                    }
                }


            }

        }

        List<Object> objectList = new ArrayList<>();
        int total = 0;
        if(list.size() > 0){
            total = list.size();
        }
        int current = 0;
        if(pageNum != 0 && pageSize > 0){
            current = (pageNum - 1)*pageSize;
        }

        objectList = list.stream().skip(current).limit(pageSize).collect(Collectors.toList());


        return new CommonPage<>(objectList,total,pageNum,pageSize);
    }

    public List<DeviceHistoryDataExportVO> deviceHistoryDataListExport(Integer deviceType, String startDate, String endDate){
        List<DeviceHistoryDataExportVO> list = new ArrayList<>();

        String tableName = "data_"+"ev"+"_history";

        List<DeviceDataHistoryMiddleVO> list1 = new ArrayList<>();
        list1 = baseMapper.QueryDeviceHistoryData(tableName,startDate,endDate);

        if(CollectionUtils.isNotEmpty(list1)){
            List<String> dateList = new ArrayList<>();
            List<String> deviceIdList = new ArrayList<>();
            for(int i=0;i<list1.size();i++){
                if(!dateList.contains(list1.get(i).getDataDate().substring(0,13))){
                    dateList.add(list1.get(i).getDataDate().substring(0,13));
                }
                if(!deviceIdList.contains(list1.get(i).getDeviceId())){
                    deviceIdList.add(list1.get(i).getDeviceId());
                }
            }
            if(CollectionUtils.isNotEmpty(dateList) && CollectionUtils.isNotEmpty(deviceIdList)){
                LambdaQueryWrapper<DmpDevice> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(DmpDevice::getDeleteFlag,0)
                        .eq(DmpDevice::getDeviceType,deviceType)
                        .in(DmpDevice::getDeviceId,deviceIdList);
                List<DmpDevice> list2 = this.list(queryWrapper);
                if(CollectionUtils.isNotEmpty(list2)){
                    for(int i=0;i<deviceIdList.size();i++){

                        for(int j=0;j<dateList.size();j++){
                            DeviceHistoryDataExportVO responseVO = new DeviceHistoryDataExportVO();
                            for(int h=0;h<list2.size();h++){
                                if(deviceIdList.get(i).equals(list2.get(h).getDeviceId())){
                                    String deviceName = list2.get(h).getDeviceName();
                                    responseVO.setDeviceName(deviceName);
                                    break;
                                }
                            }
                            responseVO.setDataDate(dateList.get(j)+":00:00");
                            int count = 0;
                            for(int k=0;k<list1.size();k++){
                                if(deviceIdList.get(i).equals(list1.get(k).getDeviceId()) && dateList.get(j).equals(list1.get(k).getDataDate().substring(0,13))){
                                    if(list1.get(k).getAttributeName().equals("wd")){
                                        responseVO.setWd(list1.get(k).getAttributeData());
                                        count++;
                                    }
                                    if(list1.get(k).getAttributeName().equals("sd")){
                                        responseVO.setSd(list1.get(k).getAttributeData());
                                        count++;
                                    }
                                    if(list1.get(k).getAttributeName().equals("co2")){
                                        responseVO.setCo2(list1.get(k).getAttributeData());
                                        count++;
                                    }
                                    if(list1.get(k).getAttributeName().equals("jq")){
                                        responseVO.setJq(list1.get(k).getAttributeData());
                                        count++;
                                    }
                                    if(list1.get(k).getAttributeName().equals("pm2.5")){
                                        responseVO.setPm2_5(list1.get(k).getAttributeData());
                                        count++;
                                    }
                                    if(list1.get(k).getAttributeName().equals("tvoc")){
                                        responseVO.setTvoc(list1.get(k).getAttributeData());
                                        count++;
                                    }
                                    if(list1.get(k).getAttributeName().equals("pm1.0")){
                                        responseVO.setPm1_0(list1.get(k).getAttributeData());
                                        count++;
                                    }
                                    if(list1.get(k).getAttributeName().equals("pm10")){
                                        responseVO.setPm10(list1.get(k).getAttributeData());
                                        count++;
                                    }
                                }
                            }
                            if(count > 0){
                                list.add(responseVO);
                            }

                        }
                    }
                }


            }
        }

        return list;

    }

    public List<HistoryAttributeVO> deviceHistoryDataList(String deviceId, Integer deviceType, List<String> deviceAttribute, String startDate, String endDate){
        List<HistoryAttributeVO> list = new ArrayList<>();
        switch (deviceType){
            case 504:
                for(int i=0;i<deviceAttribute.size();i++){
                    HistoryAttributeVO historyAttributeVO = new HistoryAttributeVO();

                    historyAttributeVO.setDeviceAttribute(deviceAttribute.get(i));
                    List<KeyValueVO> list2 = new ArrayList<>();

                    LambdaQueryWrapper<DataGrHistory> queryWrapper1 = Wrappers.lambdaQuery();
                    queryWrapper1.select(DataGrHistory::getAttributeData,DataGrHistory::getDataTime)
                            .eq(DataGrHistory::getDeviceId,deviceId)
                            .eq(DataGrHistory::getAttributeName,deviceAttribute.get(i))
                            .between(DataGrHistory::getDataTime,startDate,endDate)
                            .orderByDesc(DataGrHistory::getId);
                    List<DataGrHistory> grList = dataGrHistoryService.list(queryWrapper1);
                    if(CollectionUtils.isNotEmpty(grList)){
                        for(int j=0;j< grList.size();j++){
                            KeyValueVO keyValueVO = new KeyValueVO();
                            keyValueVO.setValue(grList.get(j).getAttributeData());
                            keyValueVO.setTime(grList.get(j).getDataTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                            list2.add(keyValueVO);
                        }
                    }
                    historyAttributeVO.setKvList(list2);
                    list.add(historyAttributeVO);
                }

                break;
            case 509:
                for(int i=0;i<deviceAttribute.size();i++){
                    HistoryAttributeVO historyAttributeVO = new HistoryAttributeVO();

                    historyAttributeVO.setDeviceAttribute(deviceAttribute.get(i));
                    List<KeyValueVO> list2 = new ArrayList<>();

                    LambdaQueryWrapper<DataEvHistory> queryWrapper1 = Wrappers.lambdaQuery();
                    queryWrapper1.select(DataEvHistory::getAttributeData,DataEvHistory::getDataTime)
                            .eq(DataEvHistory::getDeviceId,deviceId)
                            .eq(DataEvHistory::getAttributeName,deviceAttribute.get(i))
                            .between(DataEvHistory::getDataTime,startDate,endDate)
                            .orderByDesc(DataEvHistory::getId);
                    List<DataEvHistory> evList = dataEvHistoryService.list(queryWrapper1);
                    if(CollectionUtils.isNotEmpty(evList)){
                        for(int j=0;j< evList.size();j++){
                            KeyValueVO keyValueVO = new KeyValueVO();
                            keyValueVO.setValue(evList.get(j).getAttributeData());
                            keyValueVO.setTime(evList.get(j).getDataTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                            list2.add(keyValueVO);
                        }
                    }
                    historyAttributeVO.setKvList(list2);
                    list.add(historyAttributeVO);
                }
                break;
            case 510:
                for(int i=0;i<deviceAttribute.size();i++){
                    HistoryAttributeVO historyAttributeVO = new HistoryAttributeVO();

                    historyAttributeVO.setDeviceAttribute(deviceAttribute.get(i));
                    List<KeyValueVO> list2 = new ArrayList<>();

                    LambdaQueryWrapper<DataLgHistory> queryWrapper1 = Wrappers.lambdaQuery();
                    queryWrapper1.select(DataLgHistory::getAttributeData,DataLgHistory::getDataTime)
                            .eq(DataLgHistory::getDeviceId,deviceId)
                            .eq(DataLgHistory::getAttributeName,deviceAttribute.get(i))
                            .between(DataLgHistory::getDataTime,startDate,endDate)
                            .orderByDesc(DataLgHistory::getId);
                    List<DataLgHistory> lgList = dataLgHistoryService.list(queryWrapper1);
                    if(CollectionUtils.isNotEmpty(lgList)){
                        for(int j=0;j< lgList.size();j++){
                            KeyValueVO keyValueVO = new KeyValueVO();
                            keyValueVO.setValue(lgList.get(j).getAttributeData());
                            keyValueVO.setTime(lgList.get(j).getDataTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                            list2.add(keyValueVO);
                        }
                    }
                    historyAttributeVO.setKvList(list2);
                    list.add(historyAttributeVO);
                }

                break;
        }
        return list;

    }


    @Override
    public Map<String,Object> evBuildHealth(){
        Map<String,Object> map = new HashMap<>();
        float co2 = attributeStatistic(509,"co2");
        map.put("co2",co2);
        float jq = attributeStatistic(509,"jq");
        map.put("jq",jq);
        float pm2_5 = attributeStatistic(509,"pm2.5");
        map.put("pm2.5",pm2_5);
        float pm1_0 = attributeStatistic(509,"pm1.0");
        map.put("pm1.0",pm1_0);
        float pm10 = attributeStatistic(509,"pm10");
        map.put("pm10",pm10);
        float tvoc = attributeStatistic(509,"tvoc");
        map.put("tvoc",tvoc);
        float wd = attributeStatistic(509,"wd");
        map.put("wd",wd);
        float sd = attributeStatistic(509,"sd");
        map.put("sd",sd);

        return map;
    }

    public float attributeStatistic(Integer deviceType,String attribute_name){
        float f = 0;
        int deviceCount = 0;
//        LambdaQueryWrapper<DmpDevice> queryWrapper = Wrappers.lambdaQuery();
//        queryWrapper.eq(DmpDevice::getDeviceType,deviceType)
//                .eq(DmpDevice::getDeleteFlag,0);
//        deviceCount = this.count(queryWrapper);
        LambdaQueryWrapper<DataRealTime> queryWrapper1 = Wrappers.lambdaQuery();
        queryWrapper1.select(DataRealTime::getAttributeData)
                .eq(DataRealTime::getDeviceType,deviceType)
                .eq(DataRealTime::getAttributeName,attribute_name)
                .ne(DataRealTime::getAttributeData,-50)
                .ne(DataRealTime::getAttributeData,0);
        List<DataRealTime> list = dataRealTimeService.list(queryWrapper1);
        if(list.size() > 0){
            for(int i=0;i<list.size();i++){
                f += Float.parseFloat(list.get(i).getAttributeData());
                deviceCount++;
            }
        }
        float data = f/deviceCount;
        return data;
    }

}
