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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.github.jeffreyning.mybatisplus.service.MppServiceImpl;
import com.njcn.device.pq.api.LineFeignClient;
import com.njcn.device.pq.pojo.po.LineDetail;
import com.njcn.device.biz.pojo.po.Overlimit;
import com.njcn.device.pq.pojo.po.RStatIntegrityD;
import com.njcn.influxdb.utils.InfluxDbUtils;
import com.njcn.prepare.harmonic.mapper.mysql.day.RStatIntegrityDMapper;
import com.njcn.prepare.harmonic.pojo.influxdb.po.DataVPO;
import com.njcn.prepare.harmonic.pojo.param.LineParam;
import com.njcn.prepare.harmonic.service.mysql.line.IntegrityService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.influxdb.InfluxDB;
import org.influxdb.dto.BatchPoints;
import org.influxdb.dto.Point;
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.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.njcn.influxdb.param.InfluxDBPublicParam.DAY_MINUTE;

/**
 * 数据完整性统计
 *
 * @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 LineFeignClient lineFeignClient;

    @Override
    @Async("asyncExecutor")
    public String computeDataIntegrity(LineParam lineParam) {
        List<LineDetail> lineDetailList;
        if (CollUtil.isEmpty(lineParam.getLineIds())){
            List<Overlimit> overLimitList = getAllLinesLimitData();
            List<String> lineList = overLimitList.stream().map(Overlimit::getId).collect(Collectors.toList());
            lineDetailList = lineFeignClient.getLineDetail(lineList).getData();
        }else {
            lineDetailList = lineFeignClient.getLineDetail(lineParam.getLineIds()).getData();
        }
        if (CollUtil.isEmpty(lineDetailList)){
            return "未查询到监测点详情！";
        }
        Date dateOut = DateUtil.parse(lineParam.getDataDate());
        List<String> records = new ArrayList<>();
        for (LineDetail lineDetail :lineDetailList){
            Map<String, String> tags = new HashMap<>();
            Map<String, Object> fields = new HashMap<>();
            tags.put("line_id",lineDetail.getId());
            fields.put("due",DAY_MINUTE/lineDetail.getTimeInterval());
            int dataCount = getDataCount(lineDetail.getId(),lineParam.getDataDate());
            fields.put("real",dataCount);
            Point point = influxDbUtils.pointBuilder("pqs_integrity", dateOut.getTime(), TimeUnit.MILLISECONDS,tags, fields);
            BatchPoints batchPoints = BatchPoints.database(influxDbUtils.getDbName()).tag("line_id", lineDetail.getId()).retentionPolicy("").consistency(InfluxDB.ConsistencyLevel.ALL).build();
            batchPoints.point(point);
            records.add(batchPoints.lineProtocol());
        }
        //InfluxDb入表pqs_integrity
        influxDbUtils.batchInsert(influxDbUtils.getDbName(),"", InfluxDB.ConsistencyLevel.ALL, records);
        return "成功！";
    }

    @Override
    @Async("asyncExecutor")
    public void dataIntegrity(LineParam lineParam,String time) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String data = time + " 00:00:00";
        LocalDateTime dateTime = LocalDateTime.parse(data,df);
        List<LineDetail> lineDetailList = new ArrayList<>();
        if (CollUtil.isEmpty(lineParam.getLineIds())){
            List<Overlimit> overLimitList = getAllLinesLimitData();
            List<String> lineList = overLimitList.stream().map(Overlimit::getId).collect(Collectors.toList());
            lineDetailList = lineFeignClient.getLineDetail(lineList).getData();
        }else {
            lineDetailList = lineFeignClient.getLineDetail(lineParam.getLineIds()).getData();
        }
        List<RStatIntegrityD> list = new ArrayList<>();
        for (LineDetail lineDetail :lineDetailList){
            int dataCount = getDataCount(lineDetail.getId(),time);
            RStatIntegrityD integrityDpo = new RStatIntegrityD();
            integrityDpo.setTimeId(dateTime);
            integrityDpo.setLineIndex(lineDetail.getId());
            integrityDpo.setDueTime(DAY_MINUTE/lineDetail.getTimeInterval());
            integrityDpo.setRealTime(dataCount);
            list.add(integrityDpo);
        }
        this.saveOrUpdateBatchByMultiId(list,500);
    }

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

    private List<Overlimit> getAllLinesLimitData() {
        return lineFeignClient.getAllLineOverLimit("harmonic-boot","").getData();
    }
}
