package com.njcn.harmonic.service.majornetwork.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.param.StatisticsBizBaseParam;
import com.njcn.device.biz.commApi.CommLineClient;
import com.njcn.device.biz.pojo.dto.LineALLInfoDTO;
import com.njcn.device.pq.api.DeptLineFeignClient;
import com.njcn.harmonic.mapper.majornetwork.RMpPartHarmonicDetailDMapper;
import com.njcn.harmonic.pojo.dto.RMpPartHarmonicDetailDTO;
import com.njcn.harmonic.pojo.param.RMpPartHarmonicDetailQueryParam;
import com.njcn.harmonic.pojo.po.RMpPartHarmonicDetailD;
import com.njcn.harmonic.pojo.po.day.RStatLimitRateDPO;
import com.njcn.harmonic.pojo.vo.RMpPartHarmonicDetailIconVO;
import com.njcn.harmonic.service.IRStatLimitRateDService;
import com.njcn.harmonic.service.majornetwork.RMpPartHarmonicDetailDService;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.pojo.po.DictData;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author rui.wu
 * @since 2022-10-24
 */
@Service
@RequiredArgsConstructor
public class RMpPartHarmonicDetailDServiceImpl extends ServiceImpl<RMpPartHarmonicDetailDMapper, RMpPartHarmonicDetailD> implements RMpPartHarmonicDetailDService {

    private final RMpPartHarmonicDetailDMapper rMpPartHarmonicDetailDMapper;
    private final DicDataFeignClient dicDataFeignClient;
    private final IRStatLimitRateDService irStatLimitRateDService;
    private final CommLineClient commLineClient;
    private final DeptLineFeignClient deptLineFeignClient;

    @Override
    public List<RMpPartHarmonicDetailIconVO> getRMpPartHarmonicDetailIcon(StatisticsBizBaseParam param) {
        return rMpPartHarmonicDetailDMapper.getRMpPartHarmonicDetailIcon(param);
    }

    @Override
    public Page<RMpPartHarmonicDetailDTO> getRMpPartHarmonicDetail(RMpPartHarmonicDetailQueryParam param) {

        //String start = DateUtil.format(DateUtil.offsetDay(DateUtil.parse(param.getEndTime(), DatePattern.NORM_DATE_PATTERN),-15),DatePattern.NORM_DATE_PATTERN);

        List<String> lineIdLists = deptLineFeignClient.getLineNodeByDeptId(param.getOrgNo()).getData();
        if (CollectionUtils.isEmpty(lineIdLists)){
            return  new Page<RMpPartHarmonicDetailDTO>(param.getPageNum(),param.getPageSize());
        }

        List<RStatLimitRateDPO> rStatLimitRateDPOs = irStatLimitRateDService.lambdaQuery()
                .in(RStatLimitRateDPO::getLineId,lineIdLists)
                .eq(RStatLimitRateDPO::getPhasicType,"T")
                .between(RStatLimitRateDPO::getTime, param.getStartTime()+" 00:00:00", param.getEndTime()+" 23:59:59").list();
        List<RMpPartHarmonicDetailDTO> rMpPartHarmonicDetailDTOS = new ArrayList<>();
        LocalDate date = LocalDate.parse(param.getStartTime());
        YearMonth yearMonth = YearMonth.from(date);
        int daysInMonth = yearMonth.lengthOfMonth();
         /*获取稳态统计指标*/
        List<DictData> steadyStatis = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.INDICATOR_TYPE.getCode()).getData();
        rStatLimitRateDPOs.stream().collect(Collectors.groupingBy(RStatLimitRateDPO::getLineId)).forEach((k, v) -> {
//            LineALLInfoDTO lineALLInfoDTO = tempMap.get(k);
            steadyStatis.forEach(dictData -> {

                RMpPartHarmonicDetailDTO rMpPartHarmonicDetailDTO = new RMpPartHarmonicDetailDTO();
                rMpPartHarmonicDetailDTO.setHarmonicType(dictData.getId());
                List<LocalDate> localDates = overLimitCount(dictData, v);
                rMpPartHarmonicDetailDTO.setDateList(localDates);
                rMpPartHarmonicDetailDTO.setOverLimitrate(Double.parseDouble(localDates.size()+"")/daysInMonth);
                rMpPartHarmonicDetailDTO.setMeasurementPointId(k);
//                rMpPartHarmonicDetailDTO.setMeasurementPointName(lineALLInfoDTO.getLineLineDTO().getLinename());
//                rMpPartHarmonicDetailDTO.setBarId(lineALLInfoDTO.getLineBusbarDTO().getBusBarId());
//                rMpPartHarmonicDetailDTO.setBarName(lineALLInfoDTO.getLineBusbarDTO().getBusBarName());
//                rMpPartHarmonicDetailDTO.setSustationId(lineALLInfoDTO.getLineSubStationDTO().getSubStationId());
//                rMpPartHarmonicDetailDTO.setSustationName(lineALLInfoDTO.getLineSubStationDTO().getSubStationName());
//                rMpPartHarmonicDetailDTO.setObjName(lineALLInfoDTO.getLineLineDTO().getObjName());
//                rMpPartHarmonicDetailDTO.setLoadType(lineALLInfoDTO.getLineLineDTO().getLoadType());
//                rMpPartHarmonicDetailDTO.setVoltageLevel(lineALLInfoDTO.getLineLineDTO().getVoltageLevel());


//                rMpPartHarmonicDetailDTO.setSustationName(data.getSubName());
                //todo 增加母线信息
                rMpPartHarmonicDetailDTOS.add(rMpPartHarmonicDetailDTO);

            });
        });
        List<RMpPartHarmonicDetailDTO> result = rMpPartHarmonicDetailDTOS.stream().
                filter(temp -> CollectionUtil.isEmpty(param.getHarmonicTypes()) ||param.getHarmonicTypes().contains(temp.getHarmonicType())).
                collect(Collectors.toList());


        //合并指标天数计算连续超标天数，及总超标天数
        Map<String, List<RMpPartHarmonicDetailDTO>> map = result.stream().collect(Collectors.groupingBy(RMpPartHarmonicDetailDTO::getMeasurementPointId));

        List<RMpPartHarmonicDetailDTO> rMpPartHarmonicDetailDTOList = new ArrayList<>();
        //获取所有指标类型，如何前端为空则将所有子表类型塞入HarmonicTypes
        List<String> collect = steadyStatis.stream().map(DictData::getId).collect(Collectors.toList());
        map.forEach((k,v)->{
            RMpPartHarmonicDetailDTO rMpPartHarmonicDetailDTO = new RMpPartHarmonicDetailDTO();
            RMpPartHarmonicDetailDTO rMpPartHarmonicDetailDTO1 = v.get(0);
            BeanUtils.copyProperties(rMpPartHarmonicDetailDTO1,rMpPartHarmonicDetailDTO);
            rMpPartHarmonicDetailDTO.setHarmonicTypes( CollectionUtil.isEmpty(param.getHarmonicTypes())?collect:param.getHarmonicTypes());
            List<List<LocalDate>> collect1 = v.stream().map(RMpPartHarmonicDetailDTO::getDateList).collect(Collectors.toList());
            List<LocalDate> union = collect1.stream()
                    .flatMap(List::stream)
                    .distinct()
                    .collect(Collectors.toList());
            rMpPartHarmonicDetailDTO.setDateList(union);
            rMpPartHarmonicDetailDTO.setOverLimitDay(union.size());
            rMpPartHarmonicDetailDTO.setOverLimitrate(Double.parseDouble(union.size()+"")/daysInMonth);
            int i = maxConsecutiveDays(union);
            rMpPartHarmonicDetailDTO.setOverLimitContinuous(i);
            //监测点连续越限10天的为
            //预警测点，连续越限15天的为告警监测点
            if(i<10){
                return;
            }else if(i>=10&&i<15) {
                rMpPartHarmonicDetailDTO.setWarningFlag(1);
            }else{
                rMpPartHarmonicDetailDTO.setAlarmFlag(1);
            }
            rMpPartHarmonicDetailDTOList.add(rMpPartHarmonicDetailDTO);
        });
        Page<RMpPartHarmonicDetailDTO> temp = new Page<>(param.getPageNum(),param.getPageSize());
        temp.setTotal(rMpPartHarmonicDetailDTOList.size());
        List<RMpPartHarmonicDetailDTO> collect1 = rMpPartHarmonicDetailDTOList.stream()
                .skip((param.getPageNum() - 1) * param.getPageSize()) // 跳过前面的数据项
                .limit(param.getPageSize()) // 取出指定数量的数据
                .collect(Collectors.toList());

        //获取监测点详情
        List<String> lineIds = collect1.stream().map(RMpPartHarmonicDetailDTO::getMeasurementPointId).distinct().collect(Collectors.toList());
        List<LineALLInfoDTO> data = commLineClient.getLineAllDetailList(lineIds).getData();
        System.out.println(LocalDateTime.now());
        Map<String, LineALLInfoDTO> tempMap = data.stream().collect(Collectors.toMap(lineAllInfoDTO -> lineAllInfoDTO.getLineLineDTO().getLineId(), dto -> dto));

        collect1.stream().forEach(dto->{
            LineALLInfoDTO lineALLInfoDTO = tempMap.get(dto.getMeasurementPointId());
            dto.setMeasurementPointName(lineALLInfoDTO.getLineLineDTO().getLinename());
            dto.setBarId(lineALLInfoDTO.getLineBusbarDTO().getBusBarId());
            dto.setBarName(lineALLInfoDTO.getLineBusbarDTO().getBusBarName());
            dto.setSustationId(lineALLInfoDTO.getLineSubStationDTO().getSubStationId());
            dto.setSustationName(lineALLInfoDTO.getLineSubStationDTO().getSubStationName());
            dto.setObjName(lineALLInfoDTO.getLineLineDTO().getObjName());
            dto.setLoadType(lineALLInfoDTO.getLineLineDTO().getLoadType());
            dto.setVoltageLevel(lineALLInfoDTO.getLineLineDTO().getVoltageLevel());
        });

        temp.setRecords(collect1);

        return temp;
    }


    private  List<LocalDate> overLimitCount(DictData temp,List<RStatLimitRateDPO> rStatLimitRateDPOs ) {
        List<LocalDate> localDetails = new ArrayList<>();

        if (Objects.equals(temp.getCode(), DicDataEnum.DYPC_ENUM.getCode())) {

            localDetails = rStatLimitRateDPOs.stream().filter(rStatLimitRateDPO -> rStatLimitRateDPO.getVoltageDevOvertime() > 0)
                    .map(RStatLimitRateDPO::getTime).collect(Collectors.toList());
        } else if ( Objects.equals(temp.getCode(), DicDataEnum.CSSB_ENUM.getCode())) {
            localDetails = rStatLimitRateDPOs.stream().filter(rStatLimitRateDPO -> rStatLimitRateDPO.getFlickerOvertime() > 0)
                    .map(RStatLimitRateDPO::getTime).collect(Collectors.toList());

        } else if ( Objects.equals(temp.getCode(), DicDataEnum.SXDYBPHD_ENUM.getCode())) {
            localDetails = rStatLimitRateDPOs.stream().filter(rStatLimitRateDPO -> rStatLimitRateDPO.getUbalanceOvertime() > 0)
                    .map(RStatLimitRateDPO::getTime).collect(Collectors.toList());
        }
//        else if (Objects.equals(temp.getCode(), DicDataEnum.THD_V.getCode())){
//            localDetails = rStatLimitRateDPOs.stream().filter(rStatLimitRateDPO -> rStatLimitRateDPO.getUaberranceOvertime() > 0)
//                    .map(RStatLimitRateDPO::getTime).collect(Collectors.toList());
//        }
        else if ( Objects.equals(temp.getCode(), DicDataEnum.XBDY_ENUM.getCode())) {
            localDetails = rStatLimitRateDPOs.stream().filter(rStatLimitRateDPO ->
                            rStatLimitRateDPO.getUharm2Overtime()+
                            rStatLimitRateDPO.getUharm3Overtime()+
                            rStatLimitRateDPO.getUharm4Overtime()+
                            rStatLimitRateDPO.getUharm5Overtime()+
                            rStatLimitRateDPO.getUharm6Overtime()+
                            rStatLimitRateDPO.getUharm7Overtime()+
                            rStatLimitRateDPO.getUharm8Overtime()+
                            rStatLimitRateDPO.getUharm9Overtime()+
                            rStatLimitRateDPO.getUharm10Overtime()+
                            rStatLimitRateDPO.getUharm11Overtime()+
                            rStatLimitRateDPO.getUharm12Overtime()+
                            rStatLimitRateDPO.getUharm13Overtime()+
                            rStatLimitRateDPO.getUharm14Overtime()+
                            rStatLimitRateDPO.getUharm15Overtime()+
                            rStatLimitRateDPO.getUharm16Overtime()+
                            rStatLimitRateDPO.getUharm17Overtime()+
                            rStatLimitRateDPO.getUharm18Overtime()+
                            rStatLimitRateDPO.getUharm19Overtime()+
                            rStatLimitRateDPO.getUharm20Overtime()+
                            rStatLimitRateDPO.getUharm21Overtime()+
                            rStatLimitRateDPO.getUharm22Overtime()+
                            rStatLimitRateDPO.getUharm23Overtime()+
                            rStatLimitRateDPO.getUharm24Overtime()+
                            rStatLimitRateDPO.getUharm25Overtime() > 0)
                    .map(RStatLimitRateDPO::getTime).collect(Collectors.toList());

        } else if ( Objects.equals(temp.getCode(), DicDataEnum.XBDL_ENUM.getCode())) {
            localDetails = rStatLimitRateDPOs.stream().filter(rStatLimitRateDPO ->
                            rStatLimitRateDPO.getIharm2Overtime()+
                            rStatLimitRateDPO.getIharm4Overtime()+
                            rStatLimitRateDPO.getIharm5Overtime()+
                            rStatLimitRateDPO.getIharm6Overtime()+
                            rStatLimitRateDPO.getIharm7Overtime()+
                            rStatLimitRateDPO.getIharm8Overtime()+
                            rStatLimitRateDPO.getIharm9Overtime()+
                            rStatLimitRateDPO.getIharm10Overtime()+
                            rStatLimitRateDPO.getIharm11Overtime()+
                            rStatLimitRateDPO.getIharm12Overtime()+
                            rStatLimitRateDPO.getIharm13Overtime()+
                            rStatLimitRateDPO.getIharm14Overtime()+
                            rStatLimitRateDPO.getIharm15Overtime()+
                            rStatLimitRateDPO.getIharm16Overtime()+
                            rStatLimitRateDPO.getIharm17Overtime()+
                            rStatLimitRateDPO.getIharm18Overtime()+
                            rStatLimitRateDPO.getIharm19Overtime()+
                            rStatLimitRateDPO.getIharm20Overtime()+
                            rStatLimitRateDPO.getIharm21Overtime()+
                            rStatLimitRateDPO.getIharm22Overtime()+
                            rStatLimitRateDPO.getIharm23Overtime()+
                            rStatLimitRateDPO.getIharm24Overtime()+
                            rStatLimitRateDPO.getIharm25Overtime()
                                     > 0)
                    .map(RStatLimitRateDPO::getTime).collect(Collectors.toList());


        } else if (Objects.equals(temp.getCode(), DicDataEnum.JXBDY_ENUM.getCode())){
            localDetails = rStatLimitRateDPOs.stream().filter(rStatLimitRateDPO ->
                            rStatLimitRateDPO.getInuharm1Overtime()+
                            rStatLimitRateDPO.getInuharm2Overtime()+
                            rStatLimitRateDPO.getInuharm3Overtime()+
                            rStatLimitRateDPO.getInuharm4Overtime()+
                            rStatLimitRateDPO.getInuharm5Overtime()+
                            rStatLimitRateDPO.getInuharm6Overtime()+
                            rStatLimitRateDPO.getInuharm7Overtime()+
                            rStatLimitRateDPO.getInuharm8Overtime()+
                            rStatLimitRateDPO.getInuharm9Overtime()+
                            rStatLimitRateDPO.getInuharm10Overtime()+
                            rStatLimitRateDPO.getInuharm11Overtime()+
                            rStatLimitRateDPO.getInuharm12Overtime()+
                            rStatLimitRateDPO.getInuharm13Overtime()+
                            rStatLimitRateDPO.getInuharm14Overtime()+
                            rStatLimitRateDPO.getInuharm15Overtime()+
                            rStatLimitRateDPO.getInuharm16Overtime()
                                    > 0)
                    .map(RStatLimitRateDPO::getTime).collect(Collectors.toList());

        }else if ( Objects.equals(temp.getCode(), DicDataEnum.PLPC_ENUM.getCode())) {
            localDetails = rStatLimitRateDPOs.stream().filter(rStatLimitRateDPO -> rStatLimitRateDPO.getFreqDevOvertime() > 0)
                    .map(RStatLimitRateDPO::getTime).collect(Collectors.toList());

        } else if (Objects.equals(temp.getCode(), DicDataEnum.FXDL_ENUM.getCode())){
            localDetails = rStatLimitRateDPOs.stream().filter(rStatLimitRateDPO -> rStatLimitRateDPO.getINegOvertime() > 0)
                    .map(RStatLimitRateDPO::getTime).collect(Collectors.toList());
        }
        return localDetails.stream().distinct().collect(Collectors.toList());
    }
    /**
    * @Description: maxConsecutiveDays 一组List<LocalDate> 为超标天数，判断连续超标天数
    * @Param:
    * @return: int
    * @Author: clam
    * @Date: 2024/5/21
    */
    public static int maxConsecutiveDays(List<LocalDate> signInDays) {

        Collections.sort(signInDays);
        int maxConsecutiveDays = 0;
        int currentConsecutiveDays = 1;

        for (int i = 1; i < signInDays.size(); i++) {
            long daysBetween = ChronoUnit.DAYS.between(signInDays.get(i - 1), signInDays.get(i));
            if (daysBetween == 1) {
                currentConsecutiveDays++;
            } else {
                currentConsecutiveDays = 1;
            }
            maxConsecutiveDays = Math.max(maxConsecutiveDays, currentConsecutiveDays);
        }

        return maxConsecutiveDays;
    }

    public static void main(String[] args) {
        List<LocalDate> signInDays = new ArrayList<>();
        signInDays.add(LocalDate.of(2022, 1, 1));
        signInDays.add(LocalDate.of(2022, 1, 2));
        signInDays.add(LocalDate.of(2022, 1, 3));
        signInDays.add(LocalDate.of(2022, 1, 5));
        signInDays.add(LocalDate.of(2022, 1, 6));
        signInDays.add(LocalDate.of(2022, 1, 7));
        signInDays.add(LocalDate.of(2022, 1, 8));

        signInDays.add(LocalDate.of(2022, 1, 9));
//        signInDays.add(LocalDate.of(2022, 1, 10));
//        signInDays.add(LocalDate.of(2022, 1, 11));
//        signInDays.add(LocalDate.of(2022, 1, 12));
//        signInDays.add(LocalDate.of(2022, 1, 14));
//        signInDays.add(LocalDate.of(2022, 1, 15));
//        signInDays.add(LocalDate.of(2022, 1, 16));
//        signInDays.add(LocalDate.of(2022, 1, 18));
//        signInDays.add(LocalDate.of(2022, 1, 19));
//        signInDays.add(LocalDate.of(2022, 1, 20));
//        signInDays.add(LocalDate.of(2022, 1, 21));
//        signInDays.add(LocalDate.of(2022, 1, 22));
//        signInDays.add(LocalDate.of(2022, 1, 23));
//        signInDays.add(LocalDate.of(2022, 1, 24));
//        signInDays.add(LocalDate.of(2022, 1, 25));
//        signInDays.add(LocalDate.of(2022, 1, 26));
//        signInDays.add(LocalDate.of(2022, 1, 27));
//        signInDays.add(LocalDate.of(2022, 1, 28));
//        signInDays.add(LocalDate.of(2022, 1, 29));
//        signInDays.add(LocalDate.of(2022, 1, 30));
//        signInDays.add(LocalDate.of(2022, 1, 31));
        int maxConsecutiveDays = maxConsecutiveDays(signInDays);

        System.out.println(maxConsecutiveDays);
    }
}

