package com.qmth.sop.business.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.sop.business.bean.result.SopWarnMonitorDetailResult;
import com.qmth.sop.business.bean.result.SopWarnMonitorResult;
import com.qmth.sop.business.entity.TBDelayWarn;
import com.qmth.sop.business.mapper.SopWarnMonitorMapper;
import com.qmth.sop.business.service.SopWarnMonitorService;
import com.qmth.sop.common.enums.CrmProgressMonitorEnum;
import com.qmth.sop.common.enums.SopRoleTypeEnum;
import com.qmth.sop.common.enums.WarnFieldEnum;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class SopWarnMonitorServiceImpl extends ServiceImpl<SopWarnMonitorMapper, TBDelayWarn> implements SopWarnMonitorService {

    @Override
    public List<SopWarnMonitorResult> listWarnByRegion(Long serviceUnitId, CrmProgressMonitorEnum type) {
        List<SopWarnMonitorResult> resultList = new ArrayList<>();
        List<String> warnFieldList = getWarnField();

        List<SopWarnMonitorDetailResult> warnDetailList = new ArrayList<>();
        Function<SopWarnMonitorDetailResult, List<Object>> compositeKey = null;
        if (type.equals(CrmProgressMonitorEnum.BY_LEAD)) {
            //大区经理
            warnDetailList = baseMapper.listDelayWarn(serviceUnitId, warnFieldList);
            compositeKey = warn -> Arrays.asList(warn.getLeadId(), warn.getLeadName());
        } else if (type.equals(CrmProgressMonitorEnum.BY_SUPPLIER)) {
            //项目经理所属人力商
            warnDetailList = baseMapper.listDelayWarnByUserRole(serviceUnitId, warnFieldList, SopRoleTypeEnum.PROJECT_MANAGER);
            compositeKey = warn -> Arrays.asList(warn.getSupplierId(), warn.getSupplierName());
        } else if (type.equals(CrmProgressMonitorEnum.BY_COORDINATOR)) {
            //区域协调人
            warnDetailList = baseMapper.listDelayWarnByUserRole(serviceUnitId, warnFieldList, SopRoleTypeEnum.REGION_COORDINATOR);
            compositeKey = warn -> Arrays.asList(warn.getCoordinatorId(), warn.getCoordinatorName());
        }

        Map<List<Object>, List<SopWarnMonitorDetailResult>> warnMap = warnDetailList.stream().collect(Collectors.groupingBy(compositeKey, Collectors.toList()));

        Set<Map.Entry<List<Object>, List<SopWarnMonitorDetailResult>>> entries = warnMap.entrySet();
        for (Map.Entry<List<Object>, List<SopWarnMonitorDetailResult>> entry : entries) {
            SopWarnMonitorResult result = new SopWarnMonitorResult();
            List<Object> leadList = entry.getKey();
            List<SopWarnMonitorDetailResult> detailList = entry.getValue();

            if (type.equals(CrmProgressMonitorEnum.BY_LEAD)) {
                result.setLeadId(Long.parseLong(leadList.get(0).toString()));
                result.setLeadName(leadList.get(1).toString());
            } else if (type.equals(CrmProgressMonitorEnum.BY_SUPPLIER)) {
                result.setSupplierId(Long.parseLong(leadList.get(0).toString()));
                result.setSupplierName(leadList.get(1).toString());
            } else {
                result.setCoordinatorId(Long.parseLong(leadList.get(0).toString()));
                result.setCoordinatorName(leadList.get(1).toString());
            }

            result.setTotal(detailList.size());
            resultList.add(result);
        }

        //设置预警数量和占比
        for (SopWarnMonitorResult result : resultList) {
            List<SopWarnMonitorDetailResult> filterWarnList;

            if (type.equals(CrmProgressMonitorEnum.BY_LEAD)) {
                filterWarnList = warnDetailList.stream()
                        .filter(item -> item.getLeadId().equals(result.getLeadId()))
                        .collect(Collectors.toList());
            } else if (type.equals(CrmProgressMonitorEnum.BY_SUPPLIER)) {
                filterWarnList = warnDetailList.stream()
                        .filter(item -> item.getSupplierId().equals(result.getSupplierId()))
                        .collect(Collectors.toList());
            } else {
                filterWarnList = warnDetailList.stream()
                        .filter(item -> item.getCoordinatorId().equals(result.getCoordinatorId()))
                        .collect(Collectors.toList());
            }
            getWarnFieldNum(result, filterWarnList);
        }

        //排序
        resultList = resultList.stream()
                .sorted(Comparator.comparing(SopWarnMonitorResult::getTotal).reversed())
                .collect(Collectors.toList());
        //合计
        getSum(resultList);

        return resultList;
    }

    private void getSum(List<SopWarnMonitorResult> resultList) {
        if(CollectionUtils.isNotEmpty(resultList)) {
            SopWarnMonitorResult result = new SopWarnMonitorResult();
            //总量
            int sum = resultList.stream().mapToInt(SopWarnMonitorResult::getTotal).sum();
            //扫描起始时间的预警总量
            int scanStartTimeSum = resultList.stream().mapToInt(SopWarnMonitorResult::getScanStartTimeNum).sum();
            //扫描结束时间的预警总量
            int scanEndTimeSum = resultList.stream().mapToInt(SopWarnMonitorResult::getScanEndTimeNum).sum();
            //评卷起始时间的预警总量
            int markStartTimeSum = resultList.stream().mapToInt(SopWarnMonitorResult::getMarkStartTimeNum).sum();
            //评卷结束时间的预警总量
            int markEndTimeSum = resultList.stream().mapToInt(SopWarnMonitorResult::getMarkEndTimeNum).sum();

            result.setTotal(sum);
            result.setScanStartTimeNum(scanStartTimeSum);
            result.setScanStarTimeRatio(getRatio(BigDecimal.valueOf(sum), BigDecimal.valueOf(scanStartTimeSum)));
            result.setScanEndTimeNum(scanEndTimeSum);
            result.setScanEndTimeRatio(getRatio(BigDecimal.valueOf(sum), BigDecimal.valueOf(scanEndTimeSum)));
            result.setMarkStartTimeNum(markStartTimeSum);
            result.setMarkStartTimeRatio(getRatio(BigDecimal.valueOf(sum), BigDecimal.valueOf(markStartTimeSum)));
            result.setMarkEndTimeNum(markEndTimeSum);
            result.setMarkEndTimeRatio(getRatio(BigDecimal.valueOf(sum), BigDecimal.valueOf(markEndTimeSum)));

            resultList.add(result);
        }
    }

    private void getWarnFieldNum(SopWarnMonitorResult result, List<SopWarnMonitorDetailResult> filterWarnList) {
        //按照预警字段分组，统计数量
        Map<String, List<SopWarnMonitorDetailResult>> map = filterWarnList.stream().collect(Collectors.groupingBy(SopWarnMonitorDetailResult::getFieldObj));
        for (WarnFieldEnum field : WarnFieldEnum.values()) {
            int warnNum = 0;
            String ratio = "";
            //设置预警数量和占比
            if (map.containsKey(field.getTitle())) {
                warnNum = map.get(field.getTitle()).size();
                //计算占比
                BigDecimal num = BigDecimal.valueOf(warnNum);
                BigDecimal totalNum = BigDecimal.valueOf(result.getTotal());
                ratio = getRatio(totalNum, num);
            }
            switch (field) {
            case SCAN_START_TIME:
                result.setScanStartTimeNum(warnNum);
                result.setScanStarTimeRatio(ratio);
                break;
            case SCAN_END_TIME:
                result.setScanEndTimeNum(warnNum);
                result.setScanEndTimeRatio(ratio);
                break;
            case MARK_START_TIME:
                result.setMarkStartTimeNum(warnNum);
                result.setMarkStartTimeRatio(ratio);
                break;
            case MARK_END_TIME:
                result.setMarkEndTimeNum(warnNum);
                result.setMarkEndTimeRatio(ratio);
                break;
            }
        }

    }

    private String getRatio(BigDecimal total, BigDecimal num) {
        String ratio = "";
        //计算占比
        if (total.intValue() != 0 && num.intValue() != 0) {
            num = num.divide(total, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
            NumberFormat formatter = NumberFormat.getPercentInstance();
            formatter.setMinimumFractionDigits(2);
            ratio = formatter.format(num.doubleValue() / 100);
        }
        return ratio;
    }

    private List<String> getWarnField() {
        List<String> fieldList = new ArrayList<>();
        WarnFieldEnum[] fieldEnums = WarnFieldEnum.values();
        for (WarnFieldEnum fieldEnum : fieldEnums) {
            fieldList.add(fieldEnum.getTitle());
        }
        return fieldList;
    }
}
