package com.tofly.xrtygis.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tofly.xrtygis.commons.Constant;
import com.tofly.xrtygis.custom.util.DateTimeUtil;
import com.tofly.xrtygis.entity.DmaStatistical;
import com.tofly.xrtygis.entity.dto.AnalyzeDto;
import com.tofly.xrtygis.entity.vo.LeakageAnalysisViewVo;
import com.tofly.xrtygis.entity.vo.LeakageAnalysisVo;
import com.tofly.xrtygis.entity.vo.LinePatrolCompletionRateVo;
import com.tofly.xrtygis.entity.vo.ScadaStatisticsAppVo;
import com.tofly.xrtygis.mapper.AnalyzeMapper;
import com.tofly.xrtygis.service.AnalyzeService;
import com.tofly.xrtygis.service.DmaStatisticalService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

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

/**
 * 分析实现类
 */
@Service("AnalyzeService")
public class AnalyzeServiceImpl implements AnalyzeService {

    @Autowired
    private AnalyzeMapper analyzeMapper;
    @Autowired
    private DmaStatisticalService dmaStatisticalService;

    @Override
    public Page<LeakageAnalysisVo> getLeakageAnalysis(Page page, AnalyzeDto dto) {
        QueryWrapper<AnalyzeDto> queryWrapper = new QueryWrapper();
        // 工单登记状态为 45 归档 漏点状态为 4 完成
        queryWrapper.eq("T2.LCJD", 45);
        queryWrapper.eq("T1.DISPOSE_STATE", "4");
        if(null != dto.getStartTime() && null!=dto.getEndTime()){
            queryWrapper.ge("T2.FINISH_TIME",dto.getStartTime());
            queryWrapper.le("T2.FINISH_TIME",dto.getEndTime());
        }
        if(!StringUtils.isEmpty(dto.getLeakUsers())){
            List<Long> leakUserList = Arrays.stream(dto.getLeakUsers().split(Constant.CSV)).map(s -> Long.parseLong(s.trim()))
                    .collect(Collectors.toList());
            queryWrapper.in("T2.RZRY",leakUserList);
        }
        return analyzeMapper.getLeakageAnalysisVo(page,queryWrapper);
    }

    @Override
    public List<LeakageAnalysisViewVo> getLeakageAnalysisView(AnalyzeDto dto) {
        QueryWrapper<AnalyzeDto> queryWrapper = new QueryWrapper();
        // 工单登记状态为 45 归档 漏点状态为 4 完成
        queryWrapper.eq("T2.LCJD", 45);
        queryWrapper.eq("T1.DISPOSE_STATE", "4");
        if(null != dto.getStartTime() && null!=dto.getEndTime()){
            queryWrapper.ge("T2.FINISH_TIME",dto.getStartTime());
            queryWrapper.le("T2.FINISH_TIME",dto.getEndTime());
        }
        if(!StringUtils.isEmpty(dto.getLeakUsers())){
            List<Long> leakUserList = Arrays.stream(dto.getLeakUsers().split(Constant.CSV)).map(s -> Long.parseLong(s.trim()))
                    .collect(Collectors.toList());
            queryWrapper.in("T2.RZRY",leakUserList);
        }
        return analyzeMapper.getLeakageAnalysisViewVo(queryWrapper);
    }
    @Override
    public Page<LinePatrolCompletionRateVo> getLinePatrolCompletionRateVo(Page page,AnalyzeDto dto){
        List<LinePatrolCompletionRateVo> voList = new ArrayList<>();
        List<DmaStatistical> list = dmaStatisticalService.list(new QueryWrapper<DmaStatistical>().lambda()
                .ge(null != dto.getStartTime(), DmaStatistical::getStatisticalDate, dto.getStartTime())
                .le(null != dto.getEndTime(), DmaStatistical::getStatisticalDate, dto.getEndTime()));
        // 按照月份分组
        if(null!=list && list.size()>0){
            Map<Date, List<DmaStatistical>> dateListMap = list.stream().collect(Collectors.groupingBy(DmaStatistical::getStatisticalDate));
            // 由于巡检统计和分区无关 因此只获取一条数据
            dateListMap.forEach((k,v)->{
                LinePatrolCompletionRateVo vo = new LinePatrolCompletionRateVo();
                vo.setMonth(DateTimeUtil.getLocalDate(k,DateTimeUtil.MONTHS_YEARS_FORMAT));
                DmaStatistical dmaStatistical = v.get(0);
                BigDecimal totalPlanPipeLength = dmaStatistical.getTotalPlanPipeLength();
                BigDecimal planTotalDistanceLength = dmaStatistical.getPlanTotalDistanceLength();
                vo.setPlanPipeLength(totalPlanPipeLength);
                vo.setEfficientPipeLength(planTotalDistanceLength);
                if(BigDecimal.ZERO.compareTo(planTotalDistanceLength) !=0){
                    vo.setOverRate(totalPlanPipeLength.divide(planTotalDistanceLength,4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_HALF_UP));
                }else {
                    vo.setOverRate(BigDecimal.ZERO);
                }
                voList.add(vo);
            });
        }
        voList.sort(Comparator.comparing(LinePatrolCompletionRateVo::getMonth));

        List<LinePatrolCompletionRateVo> rateVos = pageList(voList, (int) page.getCurrent(), (int) page.getSize());
        page.setRecords(rateVos);
        page.setTotal(voList.size());
        return page;
    }

    @Override
    public Page<LinePatrolCompletionRateVo> getLineEfficiencyIndicator(Page page,AnalyzeDto dto) {
        List<LinePatrolCompletionRateVo> voList = new ArrayList<>();
        List<DmaStatistical> list = dmaStatisticalService.list(new QueryWrapper<DmaStatistical>().lambda()
                .ge(null != dto.getStartTime(), DmaStatistical::getStatisticalDate, dto.getStartTime())
                .le(null != dto.getEndTime(), DmaStatistical::getStatisticalDate, dto.getEndTime()));
        // 按照月份分组
        if(null!=list && list.size()>0){
            Map<Date, List<DmaStatistical>> dateListMap = list.stream().collect(Collectors.groupingBy(DmaStatistical::getStatisticalDate));
            // 由于巡检统计和分区无关 因此只获取一条数据
            dateListMap.forEach((k,v)->{
                LinePatrolCompletionRateVo vo = new LinePatrolCompletionRateVo();
                vo.setMonth(DateTimeUtil.getLocalDate(k,DateTimeUtil.MONTHS_YEARS_FORMAT));
                DmaStatistical dmaStatistical = v.get(0);
                BigDecimal totalPlanPipeLength = dmaStatistical.getTotalPlanPipeLength();
                BigDecimal planTotalDistanceLength = dmaStatistical.getPlanTotalDistanceLength()==null?BigDecimal.ZERO:dmaStatistical.getPlanTotalDistanceLength();
                BigDecimal totalLeakNum = v.stream().map(DmaStatistical::getLeakageVal).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal reduce1 = v.stream().map(DmaStatistical::getLeakageOverVal).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal overTotalLeakNum = reduce1==null?BigDecimal.ZERO:reduce1;
                vo.setPlanPipeLength(totalPlanPipeLength);
                vo.setEfficientPipeLength(planTotalDistanceLength);
                vo.setReportLeakNum(totalLeakNum);
                vo.setOverLeakNum(overTotalLeakNum);
                if(BigDecimal.ZERO.compareTo(planTotalDistanceLength) !=0){
                    vo.setOverRate(totalPlanPipeLength.divide(planTotalDistanceLength,4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_HALF_UP));
                }else {
                    vo.setOverRate(BigDecimal.ZERO);
                }
                if(BigDecimal.ZERO.compareTo(overTotalLeakNum) !=0){
                    vo.setLineEfficiencyRate(totalLeakNum.divide(overTotalLeakNum,4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_HALF_UP));
                }else {
                    vo.setLineEfficiencyRate(BigDecimal.ZERO);
                }
                voList.add(vo);
            });
        }
        voList.sort(Comparator.comparing(LinePatrolCompletionRateVo::getMonth));

        List<LinePatrolCompletionRateVo> rateVos = pageList(voList, (int) page.getCurrent(), (int) page.getSize());
        page.setRecords(rateVos);
        page.setTotal(voList.size());
        return page;
    }

    @Override
    public ScadaStatisticsAppVo getScadaStatisticsApp() {
        return analyzeMapper.getScadaStatisticsApp();
    }

    public static <T> List<T> pageList(List<T> list, int pageNum, int pageSize) {
        //计算总页数
        int page = list.size() % pageSize == 0 ? list.size() / pageSize : list.size() / pageSize + 1;
        //兼容性分页参数错误
        pageNum = pageNum <= 0 ? 1 : pageNum;
        pageNum = pageNum >= page ? page : pageNum;
        // 开始索引
        int begin = 0;
        // 结束索引
        int end = 0;
        if (pageNum != page) {
            begin = (pageNum - 1) * pageSize;
            end = begin + pageSize;
        } else {
            begin = (pageNum - 1) * pageSize;
            end = list.size();
        }
        return list.subList(begin, end);
    }
}
