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 lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

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;
        }

        int onlineMinutes = 0;
        //获取需要计算的时间
        List<String> dateRange = TimeUtil.getDateRangeAsString(param.getStartTime(), param.getEndTime());
        for (String time : dateRange) {
            Date statDate = DateUtil.parse(time);
            // 按设备分别统计
            for (CsEquipmentDeliveryPO device : devList) {
                LineCountEvaluateParam lineParam = new LineCountEvaluateParam();
                lineParam.setLineId(Collections.singletonList(device.getId()));
                lineParam.setStartTime(time);
                lineParam.setEndTime(time);
                List<PqsCommunicateDto> dayData = pqsCommunicateService.getRawData2(lineParam);
                if (CollectionUtil.isNotEmpty(dayData)) {
                    if (dayData.size() == 1) {
                        PqsCommunicateDto singleRecord = dayData.get(0);
                        long minutesFromMidnight = DateUtil.between(statDate, DateUtil.parse(singleRecord.getTime()), DateUnit.MINUTE);
                        if (online.equals(singleRecord.getType())) {
                            // 如果是在线状态，则从该时间点之后都在线
                            onlineMinutes = 1440 - (int) minutesFromMidnight;
                        } else {
                            // 如果是离线状态，则从该时间点之前都在线（假设之前是在线的）
                            onlineMinutes = (int) minutesFromMidnight;
                        }
                    } else {
                        // 多条记录，逐段计算
                        long totalOnlineMinutes = 0L;
                        Date lastTime = statDate;

                        for (int i = 0; i < dayData.size(); i++) {
                            PqsCommunicateDto current = dayData.get(i);
                            Date currentTime = DateUtil.parse(current.getTime());
                            long intervalMinutes = DateUtil.between(lastTime, currentTime, DateUnit.MINUTE);

                            if (i == 0) {
                                // 处理第一段：从0点到第一条记录
                                // 如果第一条记录是离线(type=0)，则之前是在线；如果第一条是在线(type=1)，则之前是离线
                                if (!online.equals(current.getType())) {
                                    totalOnlineMinutes += intervalMinutes;
                                }
                            } else {
                                // 处理后续段：根据上一条记录的状态判断
                                if (online.equals(dayData.get(i - 1).getType())) {
                                    totalOnlineMinutes += intervalMinutes;
                                }
                            }

                            lastTime = currentTime;
                        }

                        // 处理最后一段：从最后一条记录到当天结束
                        Date endOfDay = DateUtil.beginOfDay(DateUtil.offsetDay(statDate, 1));
                        long lastInterval = DateUtil.between(lastTime, endOfDay, DateUnit.MINUTE);
                        if (online.equals(dayData.get(dayData.size() - 1).getType())) {
                            totalOnlineMinutes += lastInterval;
                        }

                        onlineMinutes = (int) Math.min(totalOnlineMinutes, 1440);
                    }
                } else {
                    List<PqsCommunicateDto> firstData = pqsCommunicateService.getRawDataOne(lineParam);
                    if (CollectionUtil.isNotEmpty(firstData)) {
                        Date statDate2 = DateUtil.parse(firstData.get(0).getTime());
                        if (statDate.before(statDate2)) {
                            onlineMinutes = 0;
                        } else {
                            List<PqsCommunicateDto> latestData = pqsCommunicateService.getRawDataLatest(lineParam);
                            if (online.equals(latestData.get(0).getType())){
                                onlineMinutes = 1440;
                            } else {
                                onlineMinutes = 0;
                            }
                        }
                    } else {
                        //如果设备连一条记录没有，那就根本没接入，不需要统计
                        continue;
                    }
                }

                RStatOnlineRateD po = new RStatOnlineRateD();
                po.setTimeId(LocalDate.parse(time, DatePattern.NORM_DATE_FORMATTER));
                po.setDevIndex(device.getId());
                po.setOnlineMin(onlineMinutes);
                po.setOfflineMin(1440 - onlineMinutes);
                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();
    }
}
