package com.njcn.csdevice.service.impl;

import cn.hutool.core.date.DatePattern;
import com.njcn.csdevice.param.LineCountEvaluateParam;
import com.njcn.csdevice.pojo.dto.PqsCommunicateDto;
import com.njcn.csdevice.pojo.po.CsEquipmentDeliveryPO;
import com.njcn.csdevice.service.CsEquipmentDeliveryService;
import com.njcn.csdevice.service.ICsCommunicateService;
import com.njcn.influx.imapper.PqsCommunicateMapper;
import com.njcn.influx.pojo.dto.StatisticalDataDTO;
import com.njcn.influx.pojo.po.PqsCommunicate;
import com.njcn.influx.query.InfluxQueryWrapper;
import com.njcn.influx.utils.InfluxDbUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.influxdb.InfluxDB;
import org.influxdb.dto.BatchPoints;
import org.influxdb.dto.Point;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * @Description:
 * @Author: wr
 * @Date: 2025/3/7 10:13
 */
@Slf4j
@Service("InfluxdbCsCommunicateServiceImpl")
@AllArgsConstructor
public class InfluxdbCsCommunicateServiceImpl implements ICsCommunicateService {

    private final InfluxDbUtils influxDbUtils;
    private final CsEquipmentDeliveryService csEquipmentDeliveryService;
    @Resource
    private PqsCommunicateMapper pqsCommunicateMapper;
    private final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault());

    @Override
    public List<PqsCommunicateDto> getRawDataLatest(LineCountEvaluateParam lineParam) {
        List<PqsCommunicateDto> result = new ArrayList<>();
        InfluxQueryWrapper influxQueryWrapper = new InfluxQueryWrapper(PqsCommunicate.class);
        influxQueryWrapper.regular(PqsCommunicate::getDevId, lineParam.getLineId())
                .select(PqsCommunicate::getTime)
                .select(PqsCommunicate::getDevId)
                .select(PqsCommunicate::getDescription)
                .select(PqsCommunicate::getType)
                .timeDesc()
                .limit(1);
        List<PqsCommunicate> list = pqsCommunicateMapper.selectByQueryWrapper(influxQueryWrapper);
        list.forEach(item -> {
            PqsCommunicateDto dto = new PqsCommunicateDto();
            BeanUtils.copyProperties(item, dto);
            dto.setTime(DATE_TIME_FORMATTER.format(item.getTime()));
            result.add(dto);
        });
        return result;
    }

    /**
     * @Description: 获取时间段内的数据
     * @Param:
     * @return: java.util.List<com.njcn.dataProcess.dto.DataVDTO>
     * @Author: clam
     * @Date: 2025/02/24
     */
    @Override
    public List<PqsCommunicateDto> getRawData(LineCountEvaluateParam lineParam) {
        List<PqsCommunicateDto> result = new ArrayList<>();
        List<PqsCommunicate> list = getPqsCommunicateData(lineParam);
        list.forEach(item -> {
            PqsCommunicateDto dto = new PqsCommunicateDto();
            BeanUtils.copyProperties(item, dto);
            dto.setTime(DATE_TIME_FORMATTER.format(item.getTime()));
            result.add(dto);
        });
        return result;

    }

    @Override
    public List<PqsCommunicateDto> getRawDataEnd(LineCountEvaluateParam lineParam) {
        List<PqsCommunicateDto> result = new ArrayList<>();
        InfluxQueryWrapper influxQueryWrapper = new InfluxQueryWrapper(PqsCommunicate.class);
        influxQueryWrapper.regular(PqsCommunicate::getDevId, lineParam.getLineId())
                .select(PqsCommunicate::getTime)
                .select(PqsCommunicate::getDevId)
                .select(PqsCommunicate::getDescription)
                .select(PqsCommunicate::getType)
                .between(PqsCommunicate::getTime, lineParam.getStartTime(), lineParam.getEndTime())
                .timeDesc()
                .limit(1);
        List<PqsCommunicate> list = pqsCommunicateMapper.selectByQueryWrapper(influxQueryWrapper);
        list.forEach(item -> {
            PqsCommunicateDto dto = new PqsCommunicateDto();
            BeanUtils.copyProperties(item, dto);
            dto.setTime(DATE_TIME_FORMATTER.format(item.getTime()));
            result.add(dto);
        });
        return result;
    }

    @Override
    public void insertion(PqsCommunicateDto pqsCommunicateDto) {
        //根据NDID获取装置信息
        CsEquipmentDeliveryPO po = csEquipmentDeliveryService.findDevByNDid(pqsCommunicateDto.getDevId());
        InfluxQueryWrapper influxQueryWrapper = new InfluxQueryWrapper(PqsCommunicate.class);
        influxQueryWrapper.eq(PqsCommunicate::getDevId,po.getId()).timeDesc().limit(1);
        List<PqsCommunicate> pqsCommunicates = pqsCommunicateMapper.selectByQueryWrapper(influxQueryWrapper);
        //如果不存数据或者状态不一样则插入数据
       if(CollectionUtils.isEmpty(pqsCommunicates) || !Objects.equals(pqsCommunicates.get(0).getType(),pqsCommunicateDto.getType())){
           Map<String, String> tags = new HashMap<>();
           tags.put("dev_id",po.getId());
           Map<String,Object> fields = new HashMap<>();
           fields.put("type",pqsCommunicateDto.getType());
           fields.put("description",pqsCommunicateDto.getDescription());
           long time = LocalDateTime.parse(pqsCommunicateDto.getTime(),  DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
           Point point = influxDbUtils.pointBuilder("pqs_communicate", time, TimeUnit.MILLISECONDS, tags, fields);
           BatchPoints batchPoints = BatchPoints.database(influxDbUtils.getDbName()).retentionPolicy("").consistency(InfluxDB.ConsistencyLevel.ALL).build();
           batchPoints.point(point);
           influxDbUtils.batchInsert(influxDbUtils.getDbName(), "", InfluxDB.ConsistencyLevel.ALL, TimeUnit.MILLISECONDS, Collections.singletonList(batchPoints.lineProtocol()));
       }
    }


    public List<PqsCommunicate> getPqsCommunicateData(LineCountEvaluateParam lineParam) {
        InfluxQueryWrapper influxQueryWrapper = new InfluxQueryWrapper(PqsCommunicate.class);
        influxQueryWrapper.regular(PqsCommunicate::getDevId, lineParam.getLineId())
                .select(PqsCommunicate::getTime)
                .select(PqsCommunicate::getDevId)
                .select(PqsCommunicate::getDescription)
                .select(PqsCommunicate::getType)
                .between(PqsCommunicate::getTime, lineParam.getStartTime(), lineParam.getEndTime())
                .timeAsc();
        return pqsCommunicateMapper.selectByQueryWrapper(influxQueryWrapper);
    }
}
