package com.njcn.device.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.njcn.common.pojo.dto.SimpleDTO;
import com.njcn.common.utils.PubUtils;
import com.njcn.device.enums.LineBaseEnum;
import com.njcn.device.mapper.DeviceMapper;
import com.njcn.device.mapper.LineDetailMapper;
import com.njcn.device.mapper.LineMapper;
import com.njcn.device.pojo.dto.GeneralDeviceDTO;
import com.njcn.device.pojo.param.DeviceInfoParam;
import com.njcn.device.pojo.param.RunManageParam;
import com.njcn.device.pojo.po.Device;
import com.njcn.device.pojo.po.Line;
import com.njcn.device.pojo.po.LineDetail;
import com.njcn.device.pojo.vo.*;
import com.njcn.device.service.LineService;
import com.njcn.device.service.RunManageService;
import com.njcn.influxdb.utils.InfluxDbUtils;
import com.njcn.system.api.AreaFeignClient;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.web.pojo.vo.LineDataVO;
import com.njcn.device.service.TerminalBaseService;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.pojo.enums.StatisticsEnum;
import com.njcn.system.pojo.po.DictData;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.influxdb.dto.QueryResult;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author denghuajun
 * @version 1.0.0
 * @date 2022/3/30
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RunManageServiceImpl implements RunManageService {

    private final LineService lineService;

    private final GeneralDeviceService generalDeviceService;

    private final DeviceMapper deviceMapper;

    private final LineMapper lineMapper;

    private final DicDataFeignClient dicDataFeignClient;

    private final TerminalBaseService terminalBaseService;

    private final LineDetailMapper lineDetailMapper;

    private final AreaFeignClient areaFeignClient;

    private final InfluxDbUtils influxDbUtils;

    @Override
    public List<RunManageVO> getLineLedger(RunManageParam runManageParam) {
        List<RunManageVO> runManageVOList = new ArrayList<>();
        DeviceInfoParam deviceInfoParam = new DeviceInfoParam();
        BeanUtil.copyProperties(runManageParam, deviceInfoParam);
        List<GeneralDeviceDTO> generalDeviceDTOList = generalDeviceService.getDeviceInfoAsDept(deviceInfoParam, Stream.of(0).collect(Collectors.toList()), Stream.of(1).collect(Collectors.toList()));
        List<String> lineIndexes = new ArrayList<>();
        List<String> devIndexes = new ArrayList<>();
        List<String> lineIndex = new ArrayList<>();
        if (!CollectionUtils.isEmpty(generalDeviceDTOList)) {
            for (GeneralDeviceDTO generalDeviceDTO : generalDeviceDTOList) {
                lineIndexes.addAll(generalDeviceDTO.getLineIndexes());
            }
            QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("pq_device.Com_Flag", runManageParam.getComFlag());
            queryWrapper.in("pq_device.Run_Flag", runManageParam.getRunFlag());
            List<Device> deviceList = deviceMapper.selectList(queryWrapper);
            //获取满足条件的终端id
            for (Device device : deviceList) {
                devIndexes.add(device.getId());
            }
            //根据终端id获取监测点id
            QueryWrapper<Line> lineQueryWrapper = new QueryWrapper<>();
            lineQueryWrapper.in("pq_line.pid", devIndexes);
            List<Line> lineList = lineMapper.selectList(lineQueryWrapper);
            for (Line line : lineList) {
                QueryWrapper<Line> queryWrappers = new QueryWrapper<>();
                queryWrappers.eq("pq_line.pid", line.getId());
                List<Line> lines = lineMapper.selectList(queryWrappers);
                for (Line l : lines) {
                    lineIndex.add(l.getId());
                }
            }
            lineIndexes.retainAll(lineIndex);
            Integer i = 1;
            for (String line : lineIndexes) {
                RunManageVO runManageVO = new RunManageVO();
                //获取监测点详情
                LineDetailDataVO lineDataVO = lineService.getLineDetailData(line);
                //获取越限详情
                LineOverLimitVO lineOverLimitVO = lineService.getLineOverLimitData(line);
                BeanUtil.copyProperties(lineDataVO, runManageVO);
                BeanUtil.copyProperties(lineOverLimitVO, runManageVO);
                runManageVO.setRunNo(i);
                runManageVOList.add(runManageVO);
                i++;
            }
        }
        return runManageVOList;
    }

    @Override
    public List<RunTimeVO> getRuntimeDetail(RunManageParam runManageParam) {
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
        List<RunTimeVO> runTimeVOList = new ArrayList<>();
        DeviceInfoParam deviceInfoParam = new DeviceInfoParam();
        BeanUtil.copyProperties(runManageParam, deviceInfoParam);
        List<GeneralDeviceDTO> generalDeviceDTOList = generalDeviceService.getDeviceInfoAsDept(deviceInfoParam, Stream.of(0).collect(Collectors.toList()), Stream.of(1).collect(Collectors.toList()));
        List<String> devIndexes = new ArrayList<>();
        List<String> devIndex = new ArrayList<>();
        if (!CollectionUtils.isEmpty(generalDeviceDTOList)) {
            for (GeneralDeviceDTO generalDeviceDTO : generalDeviceDTOList) {
                devIndexes.addAll(generalDeviceDTO.getDeviceIndexes());
            }
            QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("pq_device.Com_Flag", runManageParam.getComFlag());
            queryWrapper.in("pq_device.Run_Flag", runManageParam.getRunFlag());
            List<Device> deviceList = deviceMapper.selectList(queryWrapper);
            for (Device device : deviceList) {
                devIndex.add(device.getId());
            }
            devIndexes.retainAll(devIndex);
            Integer i = 1;
            for (String devIndexs : devIndexes) {
                RunTimeVO runTimeVO = new RunTimeVO();
                Device device = deviceMapper.selectById(devIndexs);
                //根据id查询当前信息的pids
                List<String> pids = Arrays.asList(lineMapper.selectById(devIndexs).getPids().split(","));
                List<String> list = new ArrayList<>(pids);
                list.add(devIndexs);
                List<LineDataVO> lineDataVOList = lineMapper.getLineDetail(list);
                runTimeVO.setRunNo(i);
                String areaId = "";
                for (LineDataVO lineDataVO : lineDataVOList) {
                    switch (lineDataVO.getLevel()) {
                        case 1:
                            areaId = lineDataVO.getName();
                            break;
                        case 2:
                            runTimeVO.setGdName(lineDataVO.getName());
                            break;
                        case 3:
                            runTimeVO.setBdName(lineDataVO.getName());
                            break;
                        case 4:
                            runTimeVO.setDevName(lineDataVO.getName());
                            break;
                        default:
                            break;
                    }
                }
                runTimeVO.setAreaName(areaFeignClient.selectIdArea(areaId).getData().getName());
                runTimeVO.setManufacturer(dicDataFeignClient.getDicDataById(device.getManufacturer()).getData().getName());
                runTimeVO.setComFlag(PubUtils.comFlag(device.getComFlag()));
                runTimeVO.setRunFlag(PubUtils.runFlag(device.getRunFlag()));
                runTimeVO.setIp(device.getIp());
                runTimeVO.setLoginTime(fmt.format(device.getLoginTime()));
                runTimeVO.setDevType(dicDataFeignClient.getDicDataById(device.getDevType()).getData().getName());
                runTimeVO.setPort(device.getPort().toString());
                runTimeVO.setUpdateTime(dateTimeFormatter.format(device.getUpdateTime()));
                //获取在线率
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                runTimeVO.setOnlineEvaluate(getCondition(formatter.format(DateUtil.lastMonth()), formatter.format(DateUtil.dateNew(new Date())), devIndexs) * 100);
                runTimeVOList.add(runTimeVO);
                i++;
            }
        }
        return runTimeVOList;
    }

    private Float getCondition(String startTime, String endTime, String lineId) {
        final Float[] floatList = {0.0f};
        QueryResult queryResult;
        if (!lineId.isEmpty()) {
            //组装sql语句
            String stringBuilder = "time >= '" + startTime + "' and " + "time <= '" + endTime + "' and (" + "DEV_INDEX ='" + lineId + "')";
            //sql语句
            String sql = "SELECT SUM(ONLINEMIN)/(SUM(OFFLINEMIN)+SUM(ONLINEMIN)) AS onlineRate FROM PQS_ONLINERATE WHERE " + stringBuilder;
            queryResult = influxDbUtils.query(sql);
            //处理结果集
            List<org.influxdb.dto.QueryResult.Series> list = queryResult.getResults().get(0).getSeries();
            if (!CollectionUtils.isEmpty(list)) {
                list.forEach(po -> {
                    List<List<Object>> valueList = po.getValues();
                    if (!CollectionUtils.isEmpty(valueList)) {
                        for (List<Object> value : valueList) {
                            //数据完整性 保留四位小数
                            floatList[0] = value.get(1) == null ? null : BigDecimal.valueOf(Float.parseFloat(value.get(1).toString())).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
                        }
                    }
                });
            }
            return floatList[0];
        }

        return floatList[0];
    }

    @Override
    public List<TerminalLedgerVO> getTerminalLedger(DeviceInfoParam deviceInfoParam) {
        //定义待返回终端信息
        List<GeneralDeviceDTO> generalDeviceDTOList = generalDeviceService.getDeviceInfoAsDept(deviceInfoParam, Stream.of(0).collect(Collectors.toList()), Stream.of(1).collect(Collectors.toList()));
        List<TerminalLedgerVO> terminalLedgerVOList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(generalDeviceDTOList)) {

            for (GeneralDeviceDTO generalDeviceDTO : generalDeviceDTOList) {
                if (CollectionUtil.isNotEmpty(generalDeviceDTO.getLineIndexes())) {
                    TerminalLedgerVO terminalLedgerVO = new TerminalLedgerVO();
                    terminalLedgerVO.setAreaIndex(generalDeviceDTO.getIndex());
                    terminalLedgerVO.setAreaName(generalDeviceDTO.getName());

                    List<TerminalLedgerVO.TemData> itemDataList = new ArrayList<>();
                    itemDataList.add(filterScale(generalDeviceDTO, deviceInfoParam.getScale()));
                    itemDataList.add(filterLoadType(generalDeviceDTO, deviceInfoParam.getLoadType()));
                    itemDataList.add(filterManufacturer(generalDeviceDTO, deviceInfoParam.getManufacturer()));
                    itemDataList.add(filterMonitor(generalDeviceDTO, deviceInfoParam.getMonitorFlag()));

                    terminalLedgerVO.setList(itemDataList);
                    terminalLedgerVOList.add(terminalLedgerVO);
                }
            }
        } else {

        }
        return terminalLedgerVOList;
    }

    /**
     * 过滤电压等级
     */
    private TerminalLedgerVO.TemData filterScale(GeneralDeviceDTO generalDeviceDTO, List<SimpleDTO> scales) {
        TerminalLedgerVO.TemData temData = new TerminalLedgerVO.TemData();
        temData.setName(DicDataTypeEnum.DEV_VOLTAGE.getName());
        //如果电压等级集合为空，则查询所有的电压等级
        if (CollectionUtil.isEmpty(scales)) {
            List<DictData> scaleDictData = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.DEV_VOLTAGE.getName()).getData();
            scales = scaleDictData.stream().map(dictData -> {
                SimpleDTO simpleDTO = new SimpleDTO();
                BeanUtil.copyProperties(dictData, simpleDTO);
                return simpleDTO;
            }).collect(Collectors.toList());
        }
        //监测点为空，则返回空的分类数据
        if (CollectionUtil.isEmpty(generalDeviceDTO.getLineIndexes())) {
            return null;
        }
        List<Line> lines = terminalBaseService.getLineById(generalDeviceDTO.getLineIndexes());
        List<TerminalLedgerVO.ItemData> itemDataList = new ArrayList<>();
        for (SimpleDTO simpleDTO : scales) {
            List<String> voltageScaleIds = terminalBaseService.getVoltageIdByScale(generalDeviceDTO.getVoltageIndexes(), simpleDTO.getId());
            GeneralDeviceDTO general = assembleDataByLine(simpleDTO, lines, voltageScaleIds, LineBaseEnum.SUB_V_LEVEL.getCode());
            toCountMod(itemDataList,general,1);
        }
        temData.setList(itemDataList);
        return temData;
    }

    /**
     * 过滤干扰源类型
     */
    private TerminalLedgerVO.TemData filterLoadType(GeneralDeviceDTO generalDeviceDTO,List<SimpleDTO> loadType){
        TerminalLedgerVO.TemData temData =new TerminalLedgerVO.TemData();
        temData.setName(DicDataTypeEnum.INTERFERENCE_SOURCE_TYPE.getName());
        if(CollectionUtil.isEmpty(loadType)){
            //如果为空则加载所有干扰源类型
            List<DictData> loadTypeDictData = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.INTERFERENCE_SOURCE_TYPE.getName()).getData();
            loadType = loadTypeDictData.stream().map(dictData -> {
                SimpleDTO simpleDTO = new SimpleDTO();
                BeanUtil.copyProperties(dictData,simpleDTO);
                return simpleDTO;
            }).collect(Collectors.toList());
        }
        //监测点为空，则返回空的分类数据
        if (CollectionUtil.isEmpty(generalDeviceDTO.getLineIndexes())) {
            return null;
        }
        List<Line> lines = terminalBaseService.getLineById(generalDeviceDTO.getLineIndexes());
        List<TerminalLedgerVO.ItemData> itemDataList = new ArrayList<>();
        for (SimpleDTO simpleDTO : loadType) {
            List<String> lineLoadTypeIds = terminalBaseService.getLineIdByLoadType(generalDeviceDTO.getLineIndexes(), simpleDTO.getId());
            GeneralDeviceDTO general = assembleDataByLine(simpleDTO, lines, lineLoadTypeIds, LineBaseEnum.LINE_LEVEL.getCode());
            toCountMod(itemDataList,general,2);

        }
        temData.setList(itemDataList);
        return temData;
    }

    /**
     * 过滤厂家
     */
    private TerminalLedgerVO.TemData filterManufacturer(GeneralDeviceDTO generalDeviceDTO,List<SimpleDTO> manufacturer){
        TerminalLedgerVO.TemData temData =new TerminalLedgerVO.TemData();
        temData.setName(DicDataTypeEnum.DEV_MANUFACTURER.getName());
        if(CollectionUtil.isEmpty(manufacturer)){
            //如果为空则加载所有干扰源类型
            List<DictData> manufacturerDictData = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.DEV_MANUFACTURER.getName()).getData();
            manufacturer = manufacturerDictData.stream().map(dictData -> {
                SimpleDTO simpleDTO = new SimpleDTO();
                BeanUtil.copyProperties(dictData,simpleDTO);
                return simpleDTO;
            }).collect(Collectors.toList());
        }
        //监测点为空，则返回空的分类数据
        if (CollectionUtil.isEmpty(generalDeviceDTO.getLineIndexes())) {
            return null;
        }
        List<Line> lines = terminalBaseService.getLineById(generalDeviceDTO.getLineIndexes());
        List<TerminalLedgerVO.ItemData> itemDataList = new ArrayList<>();
        for (SimpleDTO simpleDTO : manufacturer) {
            List<String> devIds = terminalBaseService.getDeviceIdByManufacturer(generalDeviceDTO.getDeviceIndexes(), simpleDTO.getId());
            GeneralDeviceDTO general = assembleDataByLine(simpleDTO, lines, devIds, LineBaseEnum.DEVICE_LEVEL.getCode());
            toCountMod(itemDataList,general,2);
        }
        temData.setList(itemDataList);
        return temData;
    }

    /**
     * 上报类型
     */
    private TerminalLedgerVO.TemData filterMonitor(GeneralDeviceDTO generalDeviceDTO,Integer monitorFlag){
        TerminalLedgerVO.TemData temData =new TerminalLedgerVO.TemData();
        temData.setName(StatisticsEnum.REPORT_TYPE.getName());
        List<Line> lines = terminalBaseService.getLineById(generalDeviceDTO.getLineIndexes());
        List<String> lineIds = lines.stream().map(Line::getId).collect(Collectors.toList());
        List<LineDetail>  lineDetailList = lineDetailMapper.selectBatchIds(lineIds);
        List<TerminalLedgerVO.ItemData> itemDataList = new ArrayList<>();
        if(monitorFlag == 2) {
            List<String> line1 = lineDetailList.stream().filter((item)->item.getMonitorFlag()==1).map(LineDetail::getId).collect(Collectors.toList());
            SimpleDTO simpleDTO = new SimpleDTO();
            simpleDTO.setName("灿能上报");
            GeneralDeviceDTO general = assembleDataByLine(simpleDTO, lines, line1, LineBaseEnum.LINE_LEVEL.getCode());
            toCountMod(itemDataList,general,2);

            List<String> line2 = lineDetailList.stream().filter((item)->item.getMonitorFlag()==0).map(LineDetail::getId).collect(Collectors.toList());
            SimpleDTO simpleDTO2 = new SimpleDTO();
            simpleDTO2.setName("非灿能上报");
            GeneralDeviceDTO general2 = assembleDataByLine(simpleDTO2, lines, line2, LineBaseEnum.LINE_LEVEL.getCode());
            toCountMod(itemDataList,general2,2);


        }else if(monitorFlag == 1){
            SimpleDTO simpleDTO = new SimpleDTO();
            simpleDTO.setName("灿能上报");
            GeneralDeviceDTO general = assembleDataByLine(simpleDTO, lines, generalDeviceDTO.getLineIndexes(), LineBaseEnum.LINE_LEVEL.getCode());
            toCountMod(itemDataList,general,2);

        }else if(monitorFlag == 0){
            SimpleDTO simpleDTO = new SimpleDTO();
            simpleDTO.setName("非灿能上报");
            GeneralDeviceDTO general = assembleDataByLine(simpleDTO, lines, generalDeviceDTO.getLineIndexes(), LineBaseEnum.LINE_LEVEL.getCode());
            toCountMod(itemDataList,general,2);
        }
        temData.setList(itemDataList);
        return temData;
    }

    private GeneralDeviceDTO assembleDataByLine(SimpleDTO simpleDTO, List<Line> lines, List<String> keyIds, Integer level) {
        GeneralDeviceDTO generalDeviceDTO = new GeneralDeviceDTO();
        generalDeviceDTO.setName(simpleDTO.getName());
        generalDeviceDTO.setIndex(simpleDTO.getId());
        if (CollectionUtil.isNotEmpty(keyIds)) {
            List<Line> tempLines = lines.stream().filter(line -> {
                String[] idsArray = line.getPids().split(",");
                if (level.equals(LineBaseEnum.LINE_LEVEL.getCode())) {
                    return keyIds.contains(line.getId());
                } else {
                    return keyIds.contains(idsArray[level]);
                }
            }).collect(Collectors.toList());
            List<String> subIndexes = new ArrayList<>(), deviceIndexes = new ArrayList<>(), lineIndexes = new ArrayList<>();
            for (Line line : tempLines) {
                String[] idsArray = line.getPids().split(",");
                subIndexes.add(idsArray[LineBaseEnum.SUB_LEVEL.getCode()]);
                deviceIndexes.add(idsArray[LineBaseEnum.DEVICE_LEVEL.getCode()]);
                lineIndexes.add(line.getId());
            }
            //排重，入参到终端综合体
            generalDeviceDTO.setSubIndexes(subIndexes.stream().distinct().collect(Collectors.toList()));
            generalDeviceDTO.setDeviceIndexes(deviceIndexes.stream().distinct().collect(Collectors.toList()));
            generalDeviceDTO.setLineIndexes(lineIndexes.stream().distinct().collect(Collectors.toList()));
        }
        return generalDeviceDTO;
    }

    /**
     * 数据组装
     */
    private void toCountMod(List<TerminalLedgerVO.ItemData> itemDataList,GeneralDeviceDTO general,int type){
        if(general.getLineIndexes().size()!=0 || general.getDeviceIndexes().size()!=0 || general.getSubIndexes().size()!=0){
            TerminalLedgerVO.ItemData itemData = new TerminalLedgerVO.ItemData();
            if(type == 1){
                //电压时候进行排序处理
                itemData.setVoltage(Float.parseFloat(general.getName().substring(0,general.getName().indexOf("k"))));
            }
            itemData.setLineCount(general.getLineIndexes().size());
            itemData.setDevCount(general.getDeviceIndexes().size());
            itemData.setSubCount(general.getSubIndexes().size());
            itemData.setDicIndex(general.getIndex());
            itemData.setDicName(general.getName());
            itemDataList.add(itemData);
        }
    }


}
