package com.njcn.prepare.harmonic.service.mysql.upload.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.jeffreyning.mybatisplus.service.MppServiceImpl;
import com.njcn.device.biz.pojo.dto.DeptGetChildrenMoreDTO;
import com.njcn.device.biz.pojo.dto.LineDevGetDTO;
import com.njcn.device.pq.pojo.po.RStatIntegrityD;
import com.njcn.harmonic.pojo.po.ROperatingIndexDPO;
import com.njcn.harmonic.pojo.po.upload.RUploadPointStatisticalDataD;
import com.njcn.prepare.harmonic.enums.UploadEnum;
import com.njcn.prepare.harmonic.mapper.mysql.area.ROperatingIndexDPOMapper;
import com.njcn.prepare.harmonic.mapper.mysql.day.RStatIntegrityDMapper;
import com.njcn.prepare.harmonic.mapper.mysql.upload.RUploadPointStatisticalDataDMapper;
import com.njcn.prepare.harmonic.pojo.bo.CalculatedParam;
import com.njcn.prepare.harmonic.pojo.dto.UploadPointStatisticalParam;
import com.njcn.prepare.harmonic.service.mysql.upload.IRUploadPointStatisticalDataDService;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.pojo.po.Dept;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 主配网监测点统计数据-日表 服务实现类
 * </p>
 *
 * @author xuyang
 * @since 2023-12-07
 */
@Service
@RequiredArgsConstructor
public class RUploadPointStatisticalDataDServiceImpl extends MppServiceImpl<RUploadPointStatisticalDataDMapper, RUploadPointStatisticalDataD> implements IRUploadPointStatisticalDataDService {

    private final DeptFeignClient deptFeignClient;
    private final ROperatingIndexDPOMapper rOperatingIndexDPOMapper;
    private final RStatIntegrityDMapper rStatIntegrityDMapper;

    /**
     * 此算法用于计算底层数据，方便国网数据上送
     * 1.表中存储所有单位，没有数据的暂时设置为0
     * 2.r_operating_index_d表中获取终端、监测点个数
     * 3.r_stat_integrity_d表中获取数据应收数、实收数
     */
    @Override
    public void insertPointStatisticalDataDay(CalculatedParam<DeptGetChildrenMoreDTO> calculatedParam) {
        List<RUploadPointStatisticalDataD> result = new ArrayList<>();
        List<UploadPointStatisticalParam> paramList = new ArrayList<>();
        //获取省级单位id
        Dept data = deptFeignClient.getRootDept().getData();
        String provinceId = deptFeignClient.getDepSonIdByDeptId(data.getId()).getData().get(0);
        Dept dept = deptFeignClient.getDeptById(provinceId).getData();
        //筛选国网上送监测点
        List<DeptGetChildrenMoreDTO> l1 = calculatedParam.getIdList();
        l1.forEach(item->{
            List<LineDevGetDTO> newList = item.getLineBaseList().stream().filter(o ->Objects.equals(o.getIsUpToGrid(),1)).collect(Collectors.toList());
            item.setLineBaseList(newList);
            UploadPointStatisticalParam uploadPointStatisticalParam = new UploadPointStatisticalParam();
            uploadPointStatisticalParam.setOrgId(item.getUnitId());
            List<LineDevGetDTO> lineInfo = item.getLineBaseList();
            uploadPointStatisticalParam.setOnlineMonitorNum(lineInfo.size());
            uploadPointStatisticalParam.setRunMonitorNum(lineInfo.size());
            uploadPointStatisticalParam.setRunTerminalNum((int)lineInfo.stream().map(LineDevGetDTO::getDevId).distinct().count());
            paramList.add(uploadPointStatisticalParam);
        });
        Map<String,List<UploadPointStatisticalParam>> devMap = paramList.stream().collect(Collectors.groupingBy(UploadPointStatisticalParam::getOrgId));
        //获取数据个数
        List<RStatIntegrityD> dataList = getStatIntegrityData(calculatedParam.getDataDate());
        //获取所有单位
        List<Dept> deptList = deptFeignClient.getAllDept().getData();
        Map<String,List<Dept>> deptMap = deptList.stream().collect(Collectors.groupingBy(Dept::getCode));
        l1.forEach(item->{
            if (Objects.equals(Integer.parseInt(UploadEnum.NJCN_DEPT_LEVEL_1.getCode()),item.getDeptLevel())){
                return;
            }
            RUploadPointStatisticalDataD rUploadPointStatisticalDataD = new RUploadPointStatisticalDataD();
            rUploadPointStatisticalDataD.setId(IdUtil.simpleUUID());
            rUploadPointStatisticalDataD.setProvinceId(dept.getCode());
            rUploadPointStatisticalDataD.setProvinceName(dept.getName());
            rUploadPointStatisticalDataD.setStatisticalDate(calculatedParam.getDataDate());
            rUploadPointStatisticalDataD.setStatisticalType(UploadEnum.STATISTICAL_TYPE_03.getCode());
            rUploadPointStatisticalDataD.setUploadStatus(Integer.parseInt(UploadEnum.UPLOAD_STATUS_0.getCode()));
            //fixme 主配网标识文档中没有,先随便定义一个,后期调整
            rUploadPointStatisticalDataD.setDistributionFlag(UploadEnum.DISTRIBUTION_FLAG_01.getCode());
            //fixme over
            judgeLevel(item.getDeptLevel(),rUploadPointStatisticalDataD,item.getUnitId(),item.getUnitName(),deptList,deptMap);
            List<UploadPointStatisticalParam> l11 = devMap.get(item.getUnitId());
            if (CollectionUtil.isNotEmpty(l11)){
                UploadPointStatisticalParam po = l11.get(0);
                rUploadPointStatisticalDataD.setRunTerminalNum(po.getRunTerminalNum());
                rUploadPointStatisticalDataD.setOnlineMonitorNum(po.getOnlineMonitorNum());
                rUploadPointStatisticalDataD.setRunMonitorNum(po.getRunMonitorNum());
                rUploadPointStatisticalDataD.setOnlineMonitorRate(po.getOnlineMonitorNum()==0?0d:BigDecimal.valueOf(po.getOnlineMonitorNum()*100.0/po.getRunMonitorNum()).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
            }
            //获取当前单位下所有的监测点，匹配监测点数据
            List<LineDevGetDTO> l2 = item.getLineBaseList();
            if (CollectionUtil.isNotEmpty(l2)){
                List<RStatIntegrityD> l3 = dataList.stream().filter(it -> l2.stream().map(LineDevGetDTO::getPointId).collect(Collectors.toList()).contains(it.getLineIndex())).collect(Collectors.toList());
                int due = l3.stream().mapToInt(RStatIntegrityD::getDueTime).sum();
                int real = l3.stream().mapToInt(RStatIntegrityD::getRealTime).sum();
                rUploadPointStatisticalDataD.setExpectCollectNum(due);
                rUploadPointStatisticalDataD.setActualCollectNum(real);
                rUploadPointStatisticalDataD.setDataFullRate(BigDecimal.valueOf(real*100.0/due).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                rUploadPointStatisticalDataD.setStationMonitorNum(l3.size());
            }
            result.add(rUploadPointStatisticalDataD);
        });
        if (CollectionUtil.isNotEmpty(result)){
            //查询数据如果有数据,将data_id置为null,这样就保留之前的唯一id
            LambdaQueryWrapper<RUploadPointStatisticalDataD> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(RUploadPointStatisticalDataD::getStatisticalDate,calculatedParam.getDataDate());
            List<RUploadPointStatisticalDataD> oldData = this.list(lambdaQueryWrapper);
            if (CollectionUtil.isNotEmpty(oldData)){
                result.forEach(item->{
                    item.setId(null);
                });
            }
            this.saveOrUpdateBatchByMultiId(result);
        }
    }

    /**
     * r_operating_index_d表中获取终端、监测点个数
     */
    public List<ROperatingIndexDPO> getOperatingIndexData(String time) {
        LambdaQueryWrapper<ROperatingIndexDPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ROperatingIndexDPO::getDataDate,time);
        return rOperatingIndexDPOMapper.selectList(lambdaQueryWrapper);
    }

    /**
     * r_stat_integrity_d表中获取数据应收数、实收数
     */
    public List<RStatIntegrityD> getStatIntegrityData(String time) {
        LambdaQueryWrapper<RStatIntegrityD> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(RStatIntegrityD::getTimeId,time);
        return rStatIntegrityDMapper.selectList(lambdaQueryWrapper);
    }

    /**
     * 判断单位层级
     */
    public void judgeLevel(Integer level, RUploadPointStatisticalDataD rUploadPointStatisticalDataD, String id, String name, List<Dept> deptList, Map<String,List<Dept>> map) {
        String result = "";
        if (Objects.equals(level,Integer.parseInt(UploadEnum.NJCN_DEPT_LEVEL_2.getCode()))){
            result = UploadEnum.STATISTICAL_LEVEL_3.getCode();
            rUploadPointStatisticalDataD.setCityId("");
            rUploadPointStatisticalDataD.setCountyId("");
        } else if (Objects.equals(level,Integer.parseInt(UploadEnum.NJCN_DEPT_LEVEL_3.getCode()))) {
            result = UploadEnum.STATISTICAL_LEVEL_4.getCode();
            rUploadPointStatisticalDataD.setCityId(id);
            rUploadPointStatisticalDataD.setCityName(name);
            rUploadPointStatisticalDataD.setCountyId("");
        } else if (Objects.equals(level,Integer.parseInt(UploadEnum.NJCN_DEPT_LEVEL_4.getCode()))) {
            result = UploadEnum.STATISTICAL_LEVEL_5.getCode();
            List<String> list = Arrays.stream(map.get(id).get(0).getPids().split(",")).map(String::trim).collect(Collectors.toList());
            String parentCode = deptList.stream().filter(o->Objects.equals(o.getId(),list.get(3))).findFirst().orElse(null).getCode();
            rUploadPointStatisticalDataD.setCityId(parentCode);
            rUploadPointStatisticalDataD.setCityName(map.get(parentCode).get(0).getName());
            rUploadPointStatisticalDataD.setCountyId(id);
            rUploadPointStatisticalDataD.setCountyName(name);
        }
        rUploadPointStatisticalDataD.setStatisticalLevel(result);
    }

}
