package com.njcn.csdevice.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.github.jeffreyning.mybatisplus.service.MppServiceImpl;
import com.njcn.csdevice.mapper.RStatOnlineRateDMapper;
import com.njcn.csdevice.param.LineCountEvaluateParam;
import com.njcn.csdevice.pojo.dto.PqsCommunicateDto;
import com.njcn.csdevice.pojo.po.CsEquipmentDeliveryPO;
import com.njcn.csdevice.pojo.po.RStatOnlineRateD;
import com.njcn.csdevice.service.CsEquipmentDeliveryService;
import com.njcn.csdevice.service.ICsCommunicateService;
import com.njcn.csdevice.service.IRStatOnlineRateDService;
import com.njcn.csdevice.util.TimeUtil;
import com.njcn.csharmonic.pojo.param.StatisticsDataParam;
import com.njcn.influx.deprecated.InfluxDBPublicParam;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 在线率日表 服务实现类
 * </p>
 *
 * @author xy
 * @since 2025-06-23
 */
@Service
@Slf4j
@AllArgsConstructor
@DS("sjzx")
public class RStatOnlineRateDServiceImpl extends MppServiceImpl<RStatOnlineRateDMapper, RStatOnlineRateD> implements IRStatOnlineRateDService {

    private final Integer online = 1;
    private final ICsCommunicateService pqsCommunicateService;
    private final CsEquipmentDeliveryService csEquipmentDeliveryService;

    @Override
    public void addData(StatisticsDataParam param) {
        List<RStatOnlineRateD> list = new ArrayList<>();
        List<CsEquipmentDeliveryPO> devList;
        //判断是否指定设备补招
        if (CollectionUtil.isNotEmpty(param.getIdList())) {
            devList = csEquipmentDeliveryService.getListByIds(param.getIdList());
        } else {
            //获取库中正常的所有装置
            devList = csEquipmentDeliveryService.getAll();
        }
        if (CollectionUtil.isEmpty(devList)) {
            return;
        }

        if (CollectionUtil.isNotEmpty(devList)) {
            //获取需要计算的时间
            List<String> dateRange = TimeUtil.getDateRangeAsString(param.getStartTime(), param.getEndTime());
            for (String time : dateRange) {
                List<PqsCommunicateDto> outCommunicateData = new ArrayList<>();
                LineCountEvaluateParam lineParam = new LineCountEvaluateParam();
                lineParam.setStartTime(time + " 00:00:00");
                lineParam.setEndTime(time + " 23:59:59");
                for (CsEquipmentDeliveryPO s : devList) {
                    lineParam.setLineId(Collections.singletonList(s.getId()));
                    List<PqsCommunicateDto> data = pqsCommunicateService.getRawDataLatest(lineParam);
                    if (CollectionUtil.isEmpty(data)) {
                        PqsCommunicateDto dto = new PqsCommunicateDto();
                        dto.setTime(time + " 00:00:00");
                        dto.setDevId(s.getId());
                        if (s.getRunStatus() == 1) {
                            dto.setType(0);
                            dto.setDescription("通讯中断");
                        } else if (s.getRunStatus() == 2) {
                            dto.setType(1);
                            dto.setDescription("通讯正常");
                        }
                        outCommunicateData.add(dto);
                    }
                    outCommunicateData.addAll(data);
                }
                Date dateOut = DateUtil.parse(time);
                for (PqsCommunicateDto pqsCommunicate : outCommunicateData) {
                    RStatOnlineRateD po = new RStatOnlineRateD();
                    Date newDate = DateUtil.parse(pqsCommunicate.getTime());
                    lineParam.setLineId(Collections.singletonList(pqsCommunicate.getDevId()));
                    RStatOnlineRateD onLineRate = onLineMinute(newDate, dateOut, pqsCommunicate.getType(), lineParam);
                    po.setTimeId(LocalDate.parse(time, DatePattern.NORM_DATE_FORMATTER));
                    po.setDevIndex(pqsCommunicate.getDevId());
                    po.setOnlineMin(onLineRate.getOnlineMin());
                    po.setOfflineMin(onLineRate.getOfflineMin());
                    list.add(po);
                }
            }
        }
        if (CollectionUtil.isNotEmpty(list)) {
            this.saveOrUpdateBatchByMultiId(list,1000);
        }
    }

    @Override
    public List<RStatOnlineRateD> getData(List<String> list, String startTime, String endTime) {
        return this.lambdaQuery()
                .in(RStatOnlineRateD::getDevIndex,list)
                .between(RStatOnlineRateD::getTimeId,startTime,endTime)
                .list();
    }


    /**
     * new的时间和当前统计时间 不是/是 同一天
     */
    private RStatOnlineRateD onLineMinute(Date newDate, Date date, Integer type, LineCountEvaluateParam lineParam) {
        RStatOnlineRateD onLineRate = new RStatOnlineRateD();
        Integer minute = 0;
        /*new的时间和当前统计时间是同一天*/
        if (DateUtil.isSameDay(newDate, date)) {
            minute = processData(newDate, date, type, lineParam);
        } else {
            /*new的时间和当前统计时间不是同一天*/
            Date nowDate = new Date();
            /*数据补招的情况下*/
            if (DateUtil.between(date, nowDate, DateUnit.DAY) > DateUtil.between(newDate, nowDate, DateUnit.DAY)) {
                minute = processData(newDate, date, null, lineParam);
            } else {
                if (online.equals(type)) {
                    minute = InfluxDBPublicParam.DAY_MINUTE;
                }
            }
        }
        onLineRate.setOnlineMin(minute);
        onLineRate.setOfflineMin(InfluxDBPublicParam.DAY_MINUTE - minute);
        return onLineRate;
    }

    private Integer processData(Date newDate, Date date, Integer type,LineCountEvaluateParam lineParam) {
        int minute = 0;
        List<PqsCommunicateDto> communicateData = pqsCommunicateService.getRawData(lineParam);
        /*当前统计时间内存在多条数据*/
        if (communicateData.size() > 1) {
            Date lastTime = null;
            long onlineTime = 0;
            long offlineTime = 0;
            for (int i = 0; i < communicateData.size(); i++) {
                long differ;
                if (i == 0) {
                    /*首次比较取统计时间*/
                    differ = DateUtil.between(date, DateUtil.parse(communicateData.get(i).getTime()), DateUnit.MINUTE);
                } else {
                    /*后续取上一次数据时间*/
                    differ = DateUtil.between(lastTime, DateUtil.parse(communicateData.get(i).getTime()), DateUnit.MINUTE);
                }
                if (online.equals(communicateData.get(i).getType())) {
                    offlineTime = offlineTime + differ;
                } else {
                    onlineTime = onlineTime + differ;
                }
                lastTime = DateUtil.parse(communicateData.get(i).getTime());
            }
            if (online.equals(communicateData.get(communicateData.size() - 1).getType())) {
                minute = InfluxDBPublicParam.DAY_MINUTE - (int) offlineTime;
            } else {
                minute = (int) onlineTime;
            }
        }
        /*当前统计时间内仅有一条数据*/
        else {
            if (type != null) {
                long differ = DateUtil.between(date, newDate, DateUnit.MINUTE);
                if (online.equals(type)) {
                    minute = InfluxDBPublicParam.DAY_MINUTE - (int) differ;
                } else {
                    minute = (int) differ;
                }
            } else {
                List<PqsCommunicateDto> communicateDataOld = pqsCommunicateService.getRawDataEnd(lineParam);
//                if (!communicateDataOld.isEmpty()){
//                    if (online.equals(communicateDataOld.get(0).getType())){
//                        minute = InfluxDBPublicParam.DAY_MINUTE;
//                    }
//                }
                if (!communicateDataOld.isEmpty()){
                    try {
                        if (online.equals(communicateDataOld.get(0).getType())){
                            minute = (int) DateUtil.between(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN).parse(communicateDataOld.get(0).getTime()), new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN).parse(lineParam.getEndTime()), DateUnit.MINUTE);
                        } else {
                            minute = (int) DateUtil.between(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN).parse(lineParam.getStartTime()), new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN).parse(communicateDataOld.get(0).getTime()), DateUnit.MINUTE);
                        }
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                } else {
                    minute = InfluxDBPublicParam.DAY_MINUTE;
                }
            }
        }
        return minute;
    }


}
