package net.northking.cctp.dw.api.service;

import net.northking.cctp.common.cache.EntityNameCache;
import net.northking.cctp.common.cache.EntityNameCatalog;
import net.northking.cctp.dw.constant.DWBaseConstant;
import net.northking.cctp.dw.db.entity.*;
import net.northking.cctp.dw.db.service.*;
import net.northking.cctp.dw.dto.BugLegacyGradeGroupDto;
import net.northking.cctp.dw.dto.ProjectDataVo;
import net.northking.cctp.dw.utils.ListUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author: puchao.ma
 * @date: 2021/12/17 11:13
 */
@Service
public class BugChartServiceImpl implements BugChartService {

    @Autowired
    private BugValidRepairRatioService bugValidRepairRatioService;

    @Autowired
    private MidUserBugGradeService midUserBugGradeService;

    @Autowired
    private BugDensityChartService bugDensityChartService;

    @Autowired
    private MtManualExecJobApiService manualExecJobApiService;

    @Autowired
    private BugLegacyGradeService bugLegacyGradeService;

    @Autowired
    private EntityNameCache entityNameCache;

    @Autowired
    private SynBugInfoService synBugInfoService;

    @Autowired
    private BugTemplateStatusApiService bugTemplateStatusApiService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    /**
     * 清空缺陷有效率和修复率
     */
    @Override
    @Transactional
    public void deleteAll() {
        BugValidRepairRatio ratio = new BugValidRepairRatio();
        bugValidRepairRatioService.deleteByExample(ratio);
    }

    /**
     * 新增缺陷有效率和修复率
     *
     * @param ratios
     */
    @Override
    @Transactional
    public void addBatch(List<BugValidRepairRatio> ratios) {
        bugValidRepairRatioService.insertByBatch(ratios);
    }

    /**
     * 清空用户缺陷等级数量中间表
     */
    @Override
    @Transactional
    public void deleteAllMid() {
        MidUserBugGrade grade = new MidUserBugGrade();
        midUserBugGradeService.deleteByExample(grade);
    }

    /**
     * 新增用户缺陷等级数量中间表
     *
     * @param ratios
     */
    @Override
    @Transactional
    public void addBatchMid(List<MidUserBugGrade> ratios) {
        midUserBugGradeService.insertByBatch(ratios);
    }

    /**
     * 新增缺陷密度
     */
    @Override
    public void addBugDensityCharts() {
        List<BugDensityChart> lists = dataIntegration();
        bugDensityChartService.addByBatch(lists);
    }

    /**
     * 缺陷密度数据整合
     * @return
     */
    private List<BugDensityChart> dataIntegration() {
        List<BugDensityChart> bugDensityCharts = new ArrayList<>();
        //  获取有效用例
        List<MidValidExecJob> validExecJobs = manualExecJobApiService.queryValidExecJob();
        //  获取用户缺陷等级数据
        List<MidUserBugGrade> bugGrades = midUserBugGradeService.findAll();

        //  系统id合并并去重
        Map<? extends String, List<MidValidExecJob>> execMap = ListUtils.groupBy(validExecJobs, MidValidExecJob::getProjectId);
        Map<? extends String, List<MidUserBugGrade>> bugMap = ListUtils.groupBy(bugGrades, MidUserBugGrade::getProjectId);
        List<String> execProIds = validExecJobs.stream().map(MidValidExecJob::getProjectId).collect(Collectors.toList());
        List<String> bugProIds = bugGrades.stream().map(MidUserBugGrade::getProjectId).collect(Collectors.toList());
        execProIds.addAll(bugProIds);
        List<String> proIds = execProIds.stream().distinct().collect(Collectors.toList());


        proIds.forEach(p->{
            Map<? extends String, List<MidValidExecJob>> execUserMap = new HashMap<>();
            List<String> execUserIds = new ArrayList<>();
            Map<? extends String, List<MidUserBugGrade>> bugUserMap = new HashMap<>();
            if (execMap.containsKey(p) && bugMap.containsKey(p)) {
                //  以创建人统计有效执行数
                List<MidValidExecJob>  jobs = execMap.get(p);
                execUserMap = ListUtils.groupBy(jobs, MidValidExecJob::getCreatedBy);
                execUserIds = jobs.stream().map(MidValidExecJob::getCreatedBy).collect(Collectors.toList());

                //  以创建人统计缺陷严重等级
                List<MidUserBugGrade>  grades = bugMap.get(p);
                bugUserMap = ListUtils.groupBy(grades, MidUserBugGrade::getCreatedBy);
                List<String> bugUserIds = grades.stream().map(MidUserBugGrade::getCreatedBy).collect(Collectors.toList());

                execUserIds.addAll(bugUserIds);
            } else if (execMap.containsKey(p) && !bugMap.containsKey(p)) {
                //  以创建人统计有效执行数
                List<MidValidExecJob>  jobs = execMap.get(p);
                execUserMap = ListUtils.groupBy(jobs, MidValidExecJob::getCreatedBy);
                execUserIds = jobs.stream().map(MidValidExecJob::getCreatedBy).collect(Collectors.toList());
            }

            List<String> userIds = execUserIds.stream().distinct().collect(Collectors.toList());

            for (String userId : userIds) {
                if (execUserMap.containsKey(userId)) {
                    BugDensityChart chart = new BugDensityChart();
                    List<MidValidExecJob> jobs = execUserMap.get(userId);
                    MidValidExecJob job = jobs.get(0);
                    chart.setTenantId(job.getTenantId());
                    chart.setProjectId(job.getProjectId());
                    int execSum = jobs.stream().mapToInt(MidValidExecJob::getValidExec).sum();
                    chart.setUserName(userId);
                    chart.setLoginNo(userId);
                    chart.setExecCount(execSum);

                    if (bugUserMap.containsKey(userId)) {
                        List<MidUserBugGrade> grades = bugUserMap.get(userId);
                        float bugNum = getBugNum(grades);
                        chart.setBugNum(bugNum);
                        double newNum = (double)bugNum / (double)execSum;
                        BigDecimal decimal = BigDecimal.valueOf(newNum);
                        float value = decimal.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
                        chart.setBugDensity(value);
                    } else {
                        chart.setBugNum(0f);
                        chart.setBugDensity(0f);
                    }
                    bugDensityCharts.add(chart);
                }
            }
        });

        return bugDensityCharts;
    }

    /**
     * 计算缺陷人员数量：A类缺陷*5 + B类缺陷*3 + C类缺陷 + D类缺陷*0.3 + E类缺陷*0.1
     * @param grades
     * @return
     */
    private float getBugNum(List<MidUserBugGrade> grades) {
        int countA = grades.stream().mapToInt(MidUserBugGrade::getGradeA).sum();
        int countB = grades.stream().mapToInt(MidUserBugGrade::getGradeB).sum();
        int countC = grades.stream().mapToInt(MidUserBugGrade::getGradeC).sum();
        int countD = grades.stream().mapToInt(MidUserBugGrade::getGradeD).sum();
        int countE = grades.stream().mapToInt(MidUserBugGrade::getGradeE).sum();
        return (float) (countA * 5 + countB * 3 + countC + countD * 0.3 + countE * 0.1);
    }

    /**
     * 清空缺陷密度
     */
    @Override
    public void deleteBugDensityCharts() {
        BugDensityChart chart = new BugDensityChart();
        bugDensityChartService.deleteByExample(chart);
    }

    /**
     * 清空缺陷遗留等级
     */
    @Override
    public void deleteAllBugLegacyGrade() {
        BugLegacyGrade grade = new BugLegacyGrade();
        bugLegacyGradeService.deleteByExample(grade);
    }

    /**
     * 新增缺陷遗留等级
     *
     * @param legacyGrades
     */
    @Override
    public void addBugLegacyGrades(List<BugLegacyGrade> legacyGrades) {
        bugLegacyGradeService.insertByBatch(legacyGrades);
    }

    /**
     * 缺陷密度
     *
     * @param projectId
     * @return
     */
    @Override
    public List<BugDensityChart> queryBugDensity(String projectId) {
        BugDensityChart chart = new BugDensityChart();
        chart.setProjectId(projectId);
        List<BugDensityChart> query = bugDensityChartService.query(chart);
        if(null!=query&&query.size()!=0){
            query.forEach(b->{b.setUserName(entityNameCache.translateById(EntityNameCatalog.WITH_LOGIN_NO,b.getLoginNo()));});
        }
        return query;
    }

    /**
     * 缺陷遗留数据处理
     */
    @Override
    public void bugLegacyGrade() {
        //  查询所有数据按proId,moduleId,bugStatus,bugGrade分组
        List<BugLegacyGradeGroupDto> all = synBugInfoService.findAllGroup();

        //  查询缺陷终态
        List<BugTemplateStatus> bugTemplateStatuses = bugTemplateStatusApiService.queryBugEndStatus();

        //  清除终态数据
        List<BugLegacyGradeGroupDto> bugManagements = all.stream().filter(a -> {
            List<String> endStatus = bugTemplateStatuses.stream()
                    .filter(b -> a.getProId().equals(b.getProjectId()))
                    .map(BugTemplateStatus::getBugStatusCode)
                    .collect(Collectors.toList());
            return org.springframework.util.CollectionUtils.isEmpty(endStatus) || !endStatus.contains(a.getBugStatus());
        }).collect(Collectors.toList());

        List<BugLegacyGrade> lists = new ArrayList<>();
        AtomicReference<String> flag = new AtomicReference<>();
        AtomicInteger sumA = new AtomicInteger(0);
        AtomicInteger sumB = new AtomicInteger(0);
        AtomicInteger sumC = new AtomicInteger(0);
        AtomicInteger sumD = new AtomicInteger(0);
        AtomicInteger sumE = new AtomicInteger(0);

        int size = bugManagements.size() ;

        for (int i = 0; i < size; i++) {
            BugLegacyGradeGroupDto a = bugManagements.get(i);
            String s = a.getProId() + a.getModuleId();

            if (StringUtils.isEmpty(flag.get())) {
                flag.getAndSet(s);
            }

            if (!flag.get().equals(s)) {
                BugLegacyGradeGroupDto groupDto = bugManagements.get(i-1);
                //  获取最终数据
                getBugLegacyGradeData(lists, sumA, sumB, sumC, sumD, sumE, groupDto);

                flag.getAndSet(s);
                sumA.getAndSet(0);
                sumB.getAndSet(0);
                sumC.getAndSet(0);
                sumD.getAndSet(0);
                sumE.getAndSet(0);
            }

            if (flag.get().equals(s)) {
                //  同一模块数据累加
                bugGradeSum(sumA, sumB, sumC, sumD, sumE, a);
            }

            //  获取最后一条数据
            if (i == size - 1) {
                if (!flag.get().equals(s)) {
                    //  同一模块数据累加
                    bugGradeSum(sumA, sumB, sumC, sumD, sumE, a);
                }

                //  获取最终数据
                getBugLegacyGradeData(lists, sumA, sumB, sumC, sumD, sumE, a);
            }
        }

        transactionTemplate.execute(s -> {
            //  每次导入数据之前先清空表数据
            deleteAllBugLegacyGrade();
            if (CollectionUtils.isNotEmpty(lists)) addBugLegacyGrades(lists);
            return Boolean.TRUE;
        });
    }

    @Override
    public List<ProjectDataVo> queryBugDensityByTenantId(String tenantId,List<String> projectIds) {
        List<ProjectDataVo> bugDensityCharts = bugDensityChartService.queryBugDensityByTenantId(tenantId,projectIds);
        if (null==bugDensityCharts||bugDensityCharts.size()==0)return new ArrayList<>();
        return bugDensityCharts;
    }

    private void getBugLegacyGradeData(List<BugLegacyGrade> lists, AtomicInteger sumA, AtomicInteger sumB, AtomicInteger sumC, AtomicInteger sumD, AtomicInteger sumE, BugLegacyGradeGroupDto groupDto) {
        BugLegacyGrade dto = new BugLegacyGrade();
        dto.setModuleId(groupDto.getModuleId());
        dto.setProjectId(groupDto.getProId());
        dto.setTenantId(groupDto.getTenantId());
        dto.setGradeA(sumA.get());
        dto.setGradeB(sumB.get());
        dto.setGradeC(sumC.get());
        dto.setGradeD(sumD.get());
        dto.setGradeE(sumE.get());
        lists.add(dto);
    }

    private void bugGradeSum(AtomicInteger sumA, AtomicInteger sumB, AtomicInteger sumC, AtomicInteger sumD, AtomicInteger sumE, BugLegacyGradeGroupDto a) {
        switch (a.getBugGrade()) {
            case DWBaseConstant.STR_STATUS_A:
                sumA.getAndAdd(a.getSum());
                break;
            case DWBaseConstant.STR_STATUS_B:
                sumB.getAndAdd(a.getSum());
                break;
            case DWBaseConstant.STR_STATUS_C:
                sumC.getAndAdd(a.getSum());
                break;
            case DWBaseConstant.STR_STATUS_D:
                sumD.getAndAdd(a.getSum());
                break;
            default:
                sumE.getAndAdd(a.getSum());
        }
    }


}
