package com.njcn.prepare.harmonic.service.mysql.Impl.line;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.github.jeffreyning.mybatisplus.service.MppServiceImpl;
import com.njcn.common.pojo.enums.common.ServerEnum;
import com.njcn.device.biz.commApi.CommTerminalGeneralClient;
import com.njcn.device.biz.pojo.dto.LineDevGetDTO;
import com.njcn.device.biz.pojo.param.DeptGetLineParam;
import com.njcn.device.pq.api.LineFeignClient;
import com.njcn.device.pq.pojo.po.RStatIntegrityD;
import com.njcn.influx.constant.InfluxDbSqlConstant;
import com.njcn.influx.deprecated.InfluxDBPublicParam;
import com.njcn.influx.imapper.DataVMapper;
import com.njcn.influx.pojo.bo.MeasurementCount;
import com.njcn.influx.pojo.constant.InfluxDBTableConstant;
import com.njcn.influx.pojo.po.DataV;
import com.njcn.influx.query.InfluxQueryWrapper;
import com.njcn.influx.utils.InfluxDbUtils;
import com.njcn.prepare.harmonic.mapper.mysql.day.RStatIntegrityDMapper;
import com.njcn.prepare.harmonic.pojo.bo.CalculatedParam;
import com.njcn.prepare.harmonic.pojo.param.LineParam;
import com.njcn.prepare.harmonic.service.mysql.line.IntegrityService;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.pojo.po.Dept;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.influxdb.dto.QueryResult;
import org.influxdb.impl.InfluxDBResultMapper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * 数据完整性统计
 *
 * @author xiaoyao
 * @version 1.0.0
 * @createTime 2022/10/24 20:07
 */

@Slf4j
@Service
@AllArgsConstructor
public class IntegrityServiceImpl extends MppServiceImpl<RStatIntegrityDMapper, RStatIntegrityD> implements IntegrityService{

    private final InfluxDbUtils influxDbUtils;

    private final CommTerminalGeneralClient commTerminalGeneralClient;

    private final DataVMapper dataVMapper;



    /********************************新算法************************************************/
    @Override
    public void dataIntegrity(CalculatedParam calculatedParam) {
        List<RStatIntegrityD> list = new ArrayList<>();
        List<String> lineIds = calculatedParam.getIdList();
        String beginDay = LocalDateTimeUtil.format(
                LocalDateTimeUtil.beginOfDay(LocalDateTimeUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN)),
                DatePattern.NORM_DATETIME_PATTERN
        );
        String endDay = LocalDateTimeUtil.format(
                LocalDateTimeUtil.endOfDay(LocalDateTimeUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN)),
                DatePattern.NORM_DATETIME_PATTERN
        );
        //以尺寸100分片
        List<List<String>> pendingIds =  ListUtils.partition(lineIds,5);
        for (List<String> pendingId : pendingIds) {
            List<LineDevGetDTO> lineDevGetDTOList = commTerminalGeneralClient.getMonitorDetailList(pendingId).getData();
            List<MeasurementCount> countList = this.getMeasurementCount(pendingId,beginDay,endDay);
            list.addAll(
                    lineDevGetDTOList.stream()
                            .map(item -> {
                                RStatIntegrityD integrityDpo = new RStatIntegrityD();
                                integrityDpo.setTimeId(LocalDateTimeUtil.parseDate(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN));
                                integrityDpo.setLineIndex(item.getPointId());
                                integrityDpo.setDueTime(InfluxDBTableConstant.DAY_MINUTE / item.getInterval());
                                integrityDpo.setRealTime(countList.stream()
                                        .filter(item2 -> Objects.equals(item.getPointId(), item2.getLineId()))
                                        .map(item2 -> (int) Double.parseDouble(item2.getFreq()))
                                        .findFirst().orElse(0)
                                );
                                return integrityDpo;
                            })
                            .collect(Collectors.toList())
            );
        }
        this.saveOrUpdateBatchByMultiId(list,1000);
    }

    /**
     * 获取data_v中各个监测点的数据总数
     * @param lineIndex 监测点索引
     * @param startTime 起始时间
     * @param endTime 结束时间
     */
    public List<MeasurementCount> getMeasurementCount(List<String> lineIndex, String startTime, String endTime) {
        InfluxQueryWrapper influxQueryWrapper = new InfluxQueryWrapper(DataV.class,MeasurementCount.class);
        influxQueryWrapper.regular(DataV::getLineId, lineIndex)
                .eq(DataV::getValueType, InfluxDbSqlConstant.MAX)
                .eq(DataV::getPhaseType, InfluxDBTableConstant.PHASE_TYPE_A)
                .count(DataV::getFreq)
                .groupBy(DataV::getLineId)
                .between(DataV::getTime, startTime, endTime);
        return dataVMapper.getMeasurementCount(influxQueryWrapper);
    }

    /********************************新算法结束************************************************/

    private int getDataCount(String lineId,String startTime,String endTime){
        QueryResult sqlResult = influxDbUtils.query("SELECT * FROM data_v WHERE time >= '" + startTime + "' and time <= '" + endTime + "' and line_id = '" + lineId + "' and phasic_type = 'A' and value_type = 'MAX' tz('Asia/Shanghai')");
        InfluxDBResultMapper resultMapper = new InfluxDBResultMapper();
        List<DataV> list = resultMapper.toPOJO(sqlResult, DataV.class);
        if (CollectionUtils.isEmpty(list)){
            return 0;
        } else {
            return list.size();
        }
    }


}
