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

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.sop.business.bean.result.CrmProgressResult;
import com.qmth.sop.business.bean.result.CrmProgressSopResult;
import com.qmth.sop.business.entity.TBSopInfo;
import com.qmth.sop.business.mapper.CrmProgressMonitorMapper;
import com.qmth.sop.business.service.CrmProgressMonitorService;
import com.qmth.sop.common.enums.CrmProcessEnum;
import com.qmth.sop.common.enums.CrmProgressMonitorEnum;
import com.qmth.sop.common.enums.SopRoleTypeEnum;
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 CrmProgressMonitorServiceImpl extends ServiceImpl<CrmProgressMonitorMapper, TBSopInfo> implements CrmProgressMonitorService {


    @Override
    public List<CrmProgressResult> listSopNum(Long serviceUnitId, CrmProgressMonitorEnum monitorEnum) {
        List<CrmProgressResult> resultList = new ArrayList<>();
        List<CrmProgressSopResult> sopList;
        Function<CrmProgressSopResult, List<Object>> compositeKey;

        //sop结果
        if (monitorEnum.equals(CrmProgressMonitorEnum.BY_LEAD)) {
            sopList = baseMapper.listSop(serviceUnitId);
            compositeKey = sop -> Arrays.asList(sop.getLeadId(), sop.getLeadName());
        } else if (monitorEnum.equals(CrmProgressMonitorEnum.BY_SUPPLIER)) {
            sopList = baseMapper.listSopByRoleType(serviceUnitId, SopRoleTypeEnum.PROJECT_MANAGER);
            compositeKey = sop -> Arrays.asList(sop.getSupplierId(), sop.getSupplierName());
        } else {
            sopList = baseMapper.listSopByRoleType(serviceUnitId, SopRoleTypeEnum.REGION_COORDINATOR);
            compositeKey = sop -> Arrays.asList(sop.getUserId(), sop.getRealName());
        }

        Map<List<Object>, List<CrmProgressSopResult>> sopMap = sopList.stream().collect(Collectors.groupingBy(compositeKey, Collectors.toList()));
        Set<Map.Entry<List<Object>, List<CrmProgressSopResult>>> entries = sopMap.entrySet();
        for (Map.Entry<List<Object>, List<CrmProgressSopResult>> entry : entries) {
            CrmProgressResult result = new CrmProgressResult();
            List<Object> list = entry.getKey();
            List<CrmProgressSopResult> crmProgressSopList = entry.getValue();

            //按照不同的类别设置大区经理、供应商、区域协调人
            if (monitorEnum.equals(CrmProgressMonitorEnum.BY_LEAD)) {
                result.setLeadId(Long.valueOf(String.valueOf(list.get(0))));
                result.setLeadName(String.valueOf(list.get(1)));
            } else if (monitorEnum.equals(CrmProgressMonitorEnum.BY_SUPPLIER)) {
                result.setSupplierId(Long.valueOf(list.get(0).toString()));
                result.setSupplierName(list.get(1).toString());
            } else {
                result.setCoordinatorId(Long.valueOf(list.get(0).toString()));
                result.setCoordinatorName(list.get(1).toString());
            }

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

        //填充各阶段sop的数量
        for (CrmProgressResult result : resultList) {

            List<CrmProgressSopResult> filterSopList;
            if (monitorEnum.equals(CrmProgressMonitorEnum.BY_LEAD)) {
                filterSopList = sopList.stream()
                        .filter(item -> item.getLeadId().equals(result.getLeadId()))
                        .collect(Collectors.toList());
            } else if (monitorEnum.equals(CrmProgressMonitorEnum.BY_SUPPLIER)) {
                filterSopList = sopList.stream()
                        .filter(item -> item.getSupplierId().equals(result.getSupplierId()))
                        .collect(Collectors.toList());
            } else {
                filterSopList = sopList.stream()
                        .filter(item -> item.getUserId().equals(result.getCoordinatorId()))
                        .collect(Collectors.toList());
            }

            //设置界面展示的阶段
            setDisplayProcess(result, filterSopList);
        }

        //大区经理的sop数量从高到低排序
        resultList = resultList.stream()
                .sorted(Comparator.comparing(CrmProgressResult::getTotal).reversed())
                .collect(Collectors.toList());
        //合计
        getSum(resultList);

        return resultList;
    }

    private void getSum(List<CrmProgressResult> resultList) {
        if (resultList != null && !resultList.isEmpty()) {
            CrmProgressResult sumResult = new CrmProgressResult();
            //计算总量
            int sum = resultList.stream().mapToInt(CrmProgressResult::getTotal).sum();
            //准备阶段的总量
            int prepareTotal = resultList.stream().mapToInt(CrmProgressResult::getPrepareSopNum).sum();
            //扫描阶段的总量
            int scanTotal = resultList.stream().mapToInt(CrmProgressResult::getScanSopNum).sum();
            //试卷阶段的总量
            int markTotal = resultList.stream().mapToInt(CrmProgressResult::getMarkSopNum).sum();
            //收尾阶段的总量
            int finalTotal = resultList.stream().mapToInt(CrmProgressResult::getFinalSopNum).sum();
            //已完成阶段的总量
            int finishTotal = resultList.stream().mapToInt(CrmProgressResult::getFinishSopNum).sum();

            sumResult.setTotal(sum);
            sumResult.setPrepareSopNum(prepareTotal);
            sumResult.setPrepareSopRatio(getRatio(BigDecimal.valueOf(sum), BigDecimal.valueOf(prepareTotal)));
            sumResult.setScanSopNum(scanTotal);
            sumResult.setScanSopRatio(getRatio(BigDecimal.valueOf(sum), BigDecimal.valueOf(scanTotal)));
            sumResult.setMarkSopNum(markTotal);
            sumResult.setMarkSopRatio(getRatio(BigDecimal.valueOf(sum), BigDecimal.valueOf(markTotal)));
            sumResult.setFinalSopNum(finalTotal);
            sumResult.setFinalSopRatio(getRatio(BigDecimal.valueOf(sum), BigDecimal.valueOf(finalTotal)));
            sumResult.setFinishSopNum(finishTotal);
            sumResult.setFinishSopRatio(getRatio(BigDecimal.valueOf(sum), BigDecimal.valueOf(finishTotal)));
            resultList.add(sumResult);
        }
    }

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

    private void setDisplayProcess(CrmProgressResult result, List<CrmProgressSopResult> filterSopList) {
        Map<String, List<CrmProgressSopResult>> map = filterSopList.stream().collect(Collectors.groupingBy(CrmProgressSopResult::getTaskName));
        Map<CrmProcessEnum, Integer> summaryMap = getCrmProcessNum(map);
        for (CrmProcessEnum process : CrmProcessEnum.values()) {
            Integer sopNum = 0;
            String ratio = "0.00%";
            //设置包含了某阶段的sop数量和占比
            if (summaryMap.containsKey(process)) {
                sopNum = summaryMap.get(process);
                //计算占比
                BigDecimal processNum = BigDecimal.valueOf(sopNum);
                BigDecimal totalNum = BigDecimal.valueOf(result.getTotal());
                ratio = getRatio(totalNum, processNum);
            }
            //设置各阶段的sop数量和占比
            switch (process) {
            case PREPARE:
                result.setPrepareSopNum(sopNum);
                result.setPrepareSopRatio(ratio);
                break;
            case SCAN:
                result.setScanSopNum(sopNum);
                result.setScanSopRatio(ratio);
                break;
            case MARK:
                result.setMarkSopNum(sopNum);
                result.setMarkSopRatio(ratio);
                break;
            case FINAL:
                result.setFinalSopNum(sopNum);
                result.setFinalSopRatio(ratio);
                break;
            case FINISH:
                result.setFinishSopNum(sopNum);
                result.setFinishSopRatio(ratio);
                break;
            }
        }
    }

    private Map<CrmProcessEnum, Integer> getCrmProcessNum(Map<String, List<CrmProgressSopResult>> processMap) {
        Map<CrmProcessEnum, Integer> summaryMap = new HashMap<>();
        processMap.forEach((k, v) -> {
            CrmProcessEnum crmProcess = CrmProcessEnum.findCrmProcessByDesc(k);
            if (crmProcess == null)
                return;
            if (!summaryMap.containsKey(crmProcess)) {
                summaryMap.put(crmProcess, v.size());
            } else {
                summaryMap.put(crmProcess, summaryMap.get(crmProcess) + v.size());
            }
        });
        return summaryMap;
    }
}
