package net.northking.cctp.dw.bus;

import com.alibaba.fastjson.JSON;
import net.northking.cctp.dw.api.service.*;
import net.northking.cctp.dw.constant.DWConstant;
import net.northking.cctp.dw.db.entity.*;
import net.northking.cctp.dw.db.service.*;
import net.northking.cctp.dw.dto.BugOverallTendencyChartDto;
import net.northking.cctp.dw.dto.Tmp2PrepareDataDto;
import net.northking.cctp.dw.schedule.ScheduleTask;
import net.northking.cctp.dw.utils.FileUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.support.TransactionTemplate;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


//@Component
public class HandleDataListener {

    private final static Logger logger = LoggerFactory.getLogger(HandleDataListener.class);

    @Autowired
    private BugOverallTendencyChartService bugOverallTendencyChartService;

    @Autowired
    private BugLifeCycleChartService bugLifeCycleChartService;

    @Autowired
    private BugLegacyGradeService bugLegacyGradeService;

    @Autowired
    private BugDensityChartService bugDensityChartService;

    @Autowired
    private MtCaseDesignApiService mtCaseDesignApiService;

    @Autowired
    private MtTestPointApiService mtTestPointApiService;

    @Autowired
    private MtManualExecJobApiService mtManualExecJobApiService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private CpProjectDetailApiService projectDetailApiService;

    @Autowired
    private MidProjectInfoService midProjectInfoService;

    @Autowired
    private ScheduleTask scheduleTask;

    @Autowired
    private ProgressChartPrepareService prepareService;

    @Autowired
    private ChartApiService chartApiService;

    @Autowired
    private MidUserBugGradeService midUserBugGradeService;

    @Autowired
    private BugGradeStatisticsService bugGradeStatisticsService;

    @Autowired
    private BugTendencyChartTmpService bugTendencyChartTmpService;

    @Autowired
    private BugStatusStatisticsService bugStatusStatisticsService;

    @Autowired
    private BugValidRepairRatioService bugValidRepairRatioService;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private MtTestChartService mtTestChartService;

    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(name = DWConstant.MQ_HANDLE_DATA_EXCHANGE, type = ExchangeTypes.TOPIC),
            value = @Queue(name = DWConstant.BugQueue.BUG_OVERALL_TENDENCY_CHART_QUEUE),
            key = DWConstant.BugRoutingKey.BUG_OVERALL_TENDENCY_CHART))
    public void syncBugTendencyChartNotice(List<BugOverallTendencyChartDto> dataList) {
        logger.info("==================syncBugTendencyChartNotice======================开始消费");
        if (dataList != null && !dataList.isEmpty()) {
            transactionTemplate.execute(transactionStatus -> {
                // 获取系统id
                List<String> projectIds = dataList.stream().map(BugOverallTendencyChartDto::getProjectId).collect(Collectors.toList());
                BugOverallTendencyChartDto item = new BugOverallTendencyChartDto();
                item.setTenantId(dataList.get(0).getTenantId());
                item.setProjectIds(projectIds);

                // 删除当前系统的数据
                SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
                BugOverallTendencyChart bugOverallTendencyChart = new BugOverallTendencyChart();
                bugOverallTendencyChart.setCreatedTime(sd.format(new Date()));
                bugOverallTendencyChart.setProjectIds(projectIds);
                bugOverallTendencyChart.setTenantId(item.getTenantId());
                bugOverallTendencyChartService.deleteByExampleByProjectIds(bugOverallTendencyChart);

                // 再插入数据
                bugOverallTendencyChartService.insertBatchByProjectId(item);

                return Boolean.TRUE;
            });
        }
        logger.info("==================syncBugTendencyChartNotice======================结束消费");
    }

    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(name = DWConstant.MQ_HANDLE_DATA_EXCHANGE, type = ExchangeTypes.TOPIC),
            value = @Queue(name = DWConstant.BugQueue.BUG_LIFE_CYCLE_QUEUE),
            key = DWConstant.BugRoutingKey.BUG_LIFE_CYCLE))
    public void syncBugLifeCycleNotice(List<BugLifeCycleChart> dataList) {
        logger.info("==================syncBugLifeCycleNotice======================开始消费");
        if (dataList != null && !dataList.isEmpty()) {
            transactionTemplate.execute(transactionStatus -> {
                // 获取系统id
                List<String> projectIds = dataList.stream().map(BugLifeCycleChart::getProjectId).collect(Collectors.toList());
                BugLifeCycleChart bugLifeCycleChart = new BugLifeCycleChart();
                bugLifeCycleChart.setTenantId(dataList.get(0).getTenantId());
                bugLifeCycleChart.setProjectIds(projectIds);

                // 先清空数据
                bugLifeCycleChartService.deleteByExampleByProjectIds(bugLifeCycleChart);

                // 批量新增数据
                bugLifeCycleChartService.insertBatch(bugLifeCycleChart);

                return Boolean.TRUE;
            });
        }
        logger.info("==================syncBugLifeCycleNotice======================结束消费");
    }

    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(name = DWConstant.MQ_HANDLE_DATA_EXCHANGE, type = ExchangeTypes.TOPIC),
            value = @Queue(name = DWConstant.BugQueue.BUG_LEGACY_GRADE_QUEUE),
            key = DWConstant.BugRoutingKey.BUG_LEGACY_GRADE))
    public void syncBugLegacyGradeNotice(List<BugLegacyGrade> dataList) {
        logger.info("==================syncBugLegacyGradeNotice======================开始消费");
        if (dataList != null && !dataList.isEmpty()) {
            transactionTemplate.execute(transactionStatus -> {
                // 获取系统id
                List<String> projectIds = dataList.stream().map(BugLegacyGrade::getProjectId).collect(Collectors.toList());
                BugLegacyGrade bugLegacyGrade = new BugLegacyGrade();
                bugLegacyGrade.setTenantId(dataList.get(0).getTenantId());
                bugLegacyGrade.setProjectIds(projectIds);

                // 清空数据
                bugLegacyGradeService.deleteByExampleByProjectIds(bugLegacyGrade);
                // 批量新增所有数据
                bugLegacyGradeService.insertBatch(bugLegacyGrade);
                return Boolean.TRUE;
            });
        }
        logger.info("==================syncBugLegacyGradeNotice======================结束消费");
    }

    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(name = DWConstant.MQ_HANDLE_DATA_EXCHANGE, type = ExchangeTypes.TOPIC),
            value = @Queue(name = DWConstant.BugQueue.BUG_DENSITY_CHART_QUEUE),
            key = DWConstant.BugRoutingKey.BUG_DENSITY_CHART))
    public void syncBugDensityChartNotice(List<MidProjectInfo> dataList) {
        logger.info("==================syncBugDensityChartNotice======================开始消费");
        if (dataList != null && !dataList.isEmpty()) {
            transactionTemplate.execute(transactionStatus -> {
                //删除所欲的数据
                midUserBugGradeService.deleteByData(dataList, dataList.get(0).getTenantId());
                //批量新增所有数据
                midUserBugGradeService.addBatch(dataList, dataList.get(0).getTenantId());
                return Boolean.TRUE;
            });

            transactionTemplate.execute(transactionStatus -> {
                //  每次导入数据之前先清空表数据
                mtManualExecJobApiService.deleteAllMidValid(dataList, dataList.get(0).getTenantId());
                // 插入数据
                mtManualExecJobApiService.validExecJob(dataList, dataList.get(0).getTenantId());
                return Boolean.TRUE;
            });

            transactionTemplate.execute(status -> {
                //删除所欲的数据
                bugDensityChartService.deleteByData(dataList, dataList.get(0).getTenantId());
                //批量新增所有数据
                bugDensityChartService.insertBatch(dataList, dataList.get(0).getTenantId());
                return Boolean.TRUE;
            });
        }
        logger.info("==================syncBugDensityChartNotice======================结束消费");
    }

    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(name = DWConstant.MQ_HANDLE_DATA_EXCHANGE, type = ExchangeTypes.TOPIC),
            value = @Queue(name = DWConstant.BugQueue.PREPARE_CHART_PROGRESS_QUEUE),
            key = DWConstant.BugRoutingKey.PREPARE_CHART_PROGRESS))
    public void prepareChartProgressData(List<MidProjectInfo> dataList) {
        logger.info("==================prepareChartProgressData======================开始消费");
        if (dataList != null && !dataList.isEmpty()) {
            long l1 = System.currentTimeMillis();
            transactionTemplate.execute(transactionStatus -> {
                // 首先根据系统id清除数据prepareChartProgressData
                Integer count = mtCaseDesignApiService.deleteMidByProjectId(dataList);
                // 然后插入数据
                Integer result = mtCaseDesignApiService.countCaseDesignInfoData(dataList, dataList.get(0).getTenantId());
                return Boolean.TRUE;
            });

            transactionTemplate.execute(transactionStatus -> {
                // 首先清空数据表
                mtTestPointApiService.deleteAllMid(dataList);
                // 然后插入数据
                Integer result = mtCaseDesignApiService.countTestPointData(dataList, dataList.get(0).getTenantId());
                return Boolean.TRUE;
            });

            transactionTemplate.execute(transactionStatus -> {
                //  每次导入数据之前先清空表数据
                mtManualExecJobApiService.deleteAllMid(dataList);
                // 再插入数据
                mtManualExecJobApiService.countExecJobData(dataList, dataList.get(0).getTenantId());
                return Boolean.TRUE;
            });

            amqpTemplate.convertAndSend(DWConstant.MQ_HANDLE_DATA_EXCHANGE, DWConstant.BugRoutingKey.FINAL_PREPARE_CHART_PROGRESS, dataList);

        }
        logger.info("==================prepareChartProgressData======================结束消费");
    }

    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(name = DWConstant.MQ_HANDLE_DATA_EXCHANGE, type = ExchangeTypes.TOPIC),
            value = @Queue(name = DWConstant.BugQueue.SYN_BUG_GRADE_QUEUE),
            key = DWConstant.BugRoutingKey.SYN_BUG_GRADE))
    public void syncBugGrade(List<SynBugInfo> dataList) {
        logger.info("==================syncBugGrade/syncBugTendencyNotice/syncBugStatusNotice/bugValidAndRepairRatio======================开始消费");
        if (dataList != null && !dataList.isEmpty()) {
            transactionTemplate.execute(transactionStatus -> {
                //批量删除当日数据
                bugGradeStatisticsService.deleteData(dataList, dataList.get(0).getTenantId());
                //批量新增当日数据
                bugGradeStatisticsService.insertBatch(dataList, dataList.get(0).getTenantId());
                return Boolean.TRUE;
            });
            transactionTemplate.execute(transactionStatus -> {
                //删除当日缺陷趋势数据
                SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
                bugTendencyChartTmpService.deleteData(dataList, sd.format(new Date()), dataList.get(0).getTenantId());
                //批量新增当日数据
                bugTendencyChartTmpService.insertBatch(dataList, dataList.get(0).getTenantId());
                return Boolean.TRUE;
            });

            transactionTemplate.execute(transactionStatus -> {
                //删除数据
                bugStatusStatisticsService.deleteData(dataList, dataList.get(0).getTenantId());
                //批量新增当日数据
                bugStatusStatisticsService.insertBatch(dataList, dataList.get(0).getTenantId());
                return Boolean.TRUE;
            });

            transactionTemplate.execute(transactionStatus -> {
                //每次导入数据之前先清空表数据
                bugValidRepairRatioService.deleteData(dataList, dataList.get(0).getTenantId());
                //批量插入数据
                bugValidRepairRatioService.addBatch(dataList, dataList.get(0).getTenantId());
                return Boolean.TRUE;
            });

        }
        logger.info("==================syncBugGrade/syncBugTendencyNotice/syncBugStatusNotice/bugValidAndRepairRatio======================结束消费");
    }


    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(name = DWConstant.MQ_HANDLE_DATA_EXCHANGE, type = ExchangeTypes.TOPIC),
            value = @Queue(name = DWConstant.BugQueue.FINAL_PREPARE_CHART_PROGRESS_QUEUE),
            key = DWConstant.BugRoutingKey.FINAL_PREPARE_CHART_PROGRESS))
    public void finalPrepareChartProgressData(List<MidProjectInfo> dataList) {
        logger.info("==================finalPrepareChartProgressData======================开始消费");
        String filePath = FileUtils.basePath + FileUtils.prepareChartProgressData;
        long startTime = System.currentTimeMillis();
        if (dataList != null && !dataList.isEmpty()) {
            FileUtils.createTxtFile(filePath);

            List<String> projectIds = dataList.stream().map(MidProjectInfo::getProjectId).collect(Collectors.toList());
            String tenantId = dataList.get(0).getTenantId();
            FileUtils.writeTxtFileAppend(filePath, "\n 0 ===============finalPrepareChartProgressData===============projectIds:" + JSON.toJSONString(projectIds));
            FileUtils.writeTxtFileAppend(filePath, "\n 0 ===============finalPrepareChartProgressData===============tenantId:" + tenantId);

            FileUtils.writeTxtFileAppend(filePath, "\n 1 ===============finalPrepareChartProgressData===============开始消费");

            long l1 = System.currentTimeMillis();
            List<MidCaseDesign> caseDesigns = mtCaseDesignApiService.findAll(dataList);
            FileUtils.writeTxtFileAppend(filePath, "\n 2 ===============mtCaseDesignApiService.findAll(dataList)===============耗时：" + (System.currentTimeMillis() - l1) + "ms");

            long l2 = System.currentTimeMillis();
            List<MidTestPoint> testPoints = mtTestPointApiService.findAll(dataList);
            FileUtils.writeTxtFileAppend(filePath, "\n 3 ===============mtTestPointApiService.findAll(dataList)===============耗时：" + (System.currentTimeMillis() - l2) + "ms");

            long l3 = System.currentTimeMillis();
            List<MidManualExecJob> execJobs = mtManualExecJobApiService.findAll(dataList);
            FileUtils.writeTxtFileAppend(filePath, "\n 4 =============== mtManualExecJobApiService.findAll(dataList)===============耗时：" + (System.currentTimeMillis() - l3) + "ms");

            long l4 = System.currentTimeMillis();
            List<MidProjectInfo> midProjectInfos = midProjectInfoService.findByProjectIds(dataList);
            FileUtils.writeTxtFileAppend(filePath, "\n 5 =============== midProjectInfoService.findByProjectIds(dataList)===============耗时：" + (System.currentTimeMillis() - l4) + "ms");

            long l5 = System.currentTimeMillis();
            //  组装数据
            List<ProgressChartPrepare> prepares = new ArrayList<>();
            midProjectInfos.forEach(p -> {
                //  数据计算
                int caseTotal = caseDesigns.stream().filter(c -> p.getProjectId().equals(c.getProjectId())).mapToInt(MidCaseDesign::getCompleted).sum();
                int testTotal = testPoints.stream().filter(t -> p.getProjectId().equals(t.getProjectId())).mapToInt(MidTestPoint::getTotal).sum();
                int passNum = execJobs.stream().filter(e -> p.getProjectId().equals(e.getProjectId())).mapToInt(MidManualExecJob::getPass).sum();
                int failNum = execJobs.stream().filter(e -> p.getProjectId().equals(e.getProjectId())).mapToInt(MidManualExecJob::getFail).sum();
                int execTotal = execJobs.stream().filter(e -> p.getProjectId().equals(e.getProjectId())).mapToInt(MidManualExecJob::getTotal).sum();
                int invalidNum = execJobs.stream().filter(e -> p.getProjectId().equals(e.getProjectId())).mapToInt(MidManualExecJob::getInvalid).sum();
                int execNum = passNum + failNum;
                int validExecTotal = execTotal - invalidNum;

                // 组装进度图系统准备数据
                ProgressChartPrepare prepare = scheduleTask.getProgressChartPrepare(p.getProjectId(), p.getTenantId(), caseTotal, testTotal, execNum, validExecTotal);
                prepares.add(prepare);

            });
            FileUtils.writeTxtFileAppend(filePath, "\n 6 =============== midProjectInfos.forEach===============耗时：" + (System.currentTimeMillis() - l5) + "ms");

            //  添加事务
            transactionTemplate.execute(s -> {
                long l7 = System.currentTimeMillis();
                //  查询并删除今天的准备数据
                Integer prePareCount = prepareService.queryTodayDeleted(dataList);
                FileUtils.writeTxtFileAppend(filePath, "\n 8 =============== queryTodayDeleted===============耗时：" + (System.currentTimeMillis() - l7) + "ms");
                //重新添加今天的数据
                long l11 = System.currentTimeMillis();
                if (CollectionUtils.isNotEmpty(prepares)) {
                    prepareService.insertByBatch(prepares);
                }
                FileUtils.writeTxtFileAppend(filePath, "\n 10 =============== prepareService.insertByBatch(prepares)===============耗时：" + (System.currentTimeMillis() - l11) + "ms");
                return Boolean.TRUE;
            });
            //封装最终队列数据对象
            Tmp2PrepareDataDto t=new Tmp2PrepareDataDto();
            t.setMidProjectInfo1(dataList);
            t.setMidProjectInfo2(midProjectInfos);
            amqpTemplate.convertAndSend(DWConstant.MQ_HANDLE_DATA_EXCHANGE, DWConstant.BugRoutingKey.TMP2_PREPARE_CHART_PROGRESS, t);
        }
        logger.info("==================finalPrepareChartProgressData======================结束消费");
        FileUtils.writeTxtFileAppend(filePath, "\n 7 ===============  finalPrepareChartProgressData消费完成====================================================================总耗时：" + (System.currentTimeMillis() - startTime) + "ms");
    }

    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(name = DWConstant.MQ_HANDLE_DATA_EXCHANGE, type = ExchangeTypes.TOPIC),
            value = @Queue(name = DWConstant.BugQueue.TMP2_PREPARE_CHART_PROGRESS_QUEUE),
            key = DWConstant.BugRoutingKey.TMP2_PREPARE_CHART_PROGRESS))
    public void tmp2PrepareChartProgressData(Tmp2PrepareDataDto tmp2PrepareDataDto) {
        logger.info("==================tmp2PrepareChartProgressData======================开始消费");
        String filePath = FileUtils.basePath + FileUtils.prepareChartProgressData;
        long startTime = System.currentTimeMillis();
        List<MidProjectInfo> dataList =tmp2PrepareDataDto.getMidProjectInfo1();
        if (dataList != null && !dataList.isEmpty()) {
            FileUtils.createTxtFile(filePath);

            List<String> projectIds = dataList.stream().map(MidProjectInfo::getProjectId).collect(Collectors.toList());
            String tenantId = dataList.get(0).getTenantId();
            FileUtils.writeTxtFileAppend(filePath, "\n 0 ===============tmp2PrepareChartProgressData===============projectIds:" + JSON.toJSONString(projectIds));
            FileUtils.writeTxtFileAppend(filePath, "\n 0 ===============tmp2PrepareChartProgressData===============tenantId:" + tenantId);

            FileUtils.writeTxtFileAppend(filePath, "\n 1 ===============tmp2PrepareChartProgressData===============开始消费");

            long l1 = System.currentTimeMillis();
            List<CpProjectDetail> details = projectDetailApiService.findByProjectIds(dataList);
            Map<String, List<CpProjectDetail>> collect1 = details.stream().collect(Collectors.groupingBy(CpProjectDetail::getProjectId));
            FileUtils.writeTxtFileAppend(filePath, "\n 2 =============== projectDetailApiService.findByProjectIds(dataList)===============耗时：" + (System.currentTimeMillis() - l1) + "ms");

            List<MidProjectInfo> midProjectInfos = tmp2PrepareDataDto.getMidProjectInfo2();

            long l3 = System.currentTimeMillis();
            //根据系统id查询各子进度图的数据
            List<MtTestChart> mtTestCharts = mtTestChartService.queryToday(dataList);
            Map<String, List<MtTestChart>> collect = mtTestCharts.stream().collect(Collectors.groupingBy(MtTestChart::getProjectId));
            //  组装数据
            Date toDay = new Date();
            List<MtTestChart> charts = new ArrayList<>();
            midProjectInfos.forEach(p -> {
                //  计算当天总进度数据
                MtTestChart chart = scheduleTask.getMtTestChart(collect1.get(p.getProjectId()), toDay, p.getProjectId(), p,collect.get(p.getProjectId()));
                if (Objects.nonNull(chart)) {
                    charts.add(chart);
                }
            });
            FileUtils.writeTxtFileAppend(filePath, "\n 4 =============== midProjectInfos.forEach===============耗时：" + (System.currentTimeMillis() - l3) + "ms");
            //处理进度图表出现断层的现象
            //  添加事务
            transactionTemplate.execute(s -> {
                long l4 = System.currentTimeMillis();
                //  查询并删除今天的总进度数据
                Integer mtTestChartCount = chartApiService.queryTodayDeleted(dataList);
                FileUtils.writeTxtFileAppend(filePath, "\n 5 =============== queryTodayDeleted===============耗时：" + (System.currentTimeMillis() - l4) + "ms");

                long l5 = System.currentTimeMillis();
                if (CollectionUtils.isNotEmpty(charts)) {
                    chartApiService.addBatchTestChart(charts);
                }
                FileUtils.writeTxtFileAppend(filePath, "\n 6 ===============  chartApiService.addBatchTestChart===============耗时：" + (System.currentTimeMillis() - l5) + "ms");

                return Boolean.TRUE;
            });
        }
        logger.info("==================tmp2PrepareChartProgressData======================结束消费");
        FileUtils.writeTxtFileAppend(filePath, "\n 7 ===============  tmp2PrepareChartProgressData消费完成====================================================================总耗时：" + (System.currentTimeMillis() - startTime) + "ms");
    }
}
