package org.jeecg.modules.diseaseAnalysis.algorithm;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.UUIDGenerator;
import org.jeecg.modules.checkData.entity.*;
import org.jeecg.modules.checkData.service.*;
import org.jeecg.modules.diseaseAnalysis.entity.*;
import org.jeecg.modules.diseaseAnalysis.service.*;
import org.jeecg.modules.dynamicStaticAnalysis.mapper.AnalysisAlgorithmMapper;
import org.jeecg.modules.utils.BeanCopyUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 分析算法
 */
@Service
@Slf4j
public class AnalysisAlgorithmLine {
    @Resource
    private AnalysisAlgorithmMapper analysisAlgorithmMapper;
    @Resource
    private IAnalysisLineBatchService analysisLineBatchService;
    @Resource
    private IAnalysisLineBatchCheckDataMapService analysisLineBatchCheckDataMapService;
    @Resource
    private IAnalysisLineBatchUnitDeviceTurnoutInfoService analysisLineBatchUnitDeviceTurnoutInfoService;
    @Resource
    private IAnalysisLineBatchUnitDeviceRailWearInfoService analysisLineBatchUnitDeviceRailWearInfoService;
    @Resource
    private IRecordsMasterTurnoutInfoService turnoutInfoService;
    @Resource
    private IRailWearRecordService railWearRecordService;
    @Resource
    private IAnalysisLineBatchUnitDeviceService unitDeviceService;
    @Resource
    private IRecordsMasterCheckService masterCheckService;

    @Transactional
    public void analysisLine(String analysisLineBatchId) {
        Map<String, Map<String, Object>> unitDeviceTable = new LinkedHashMap<>();

        // 1.1 获取分析基础数据
        AnalysisLineBatch analysisLineBatch = analysisLineBatchService.getById(analysisLineBatchId);
        //查询该批次所需要分析得采集信息批次
        List<AnalysisLineBatchCheckDataMap> analysisLineBatchCheckDataMapList = analysisLineBatchCheckDataMapService.lambdaQuery().eq(AnalysisLineBatchCheckDataMap::getAnalysisBatchId, analysisLineBatchId).list();


        // 1.2 按公里数正序排序所有1-钢轨,2-曲线,3-竖曲线,4-道岔
        List<Map<String, Object>> unitDeviceList = analysisAlgorithmMapper.getUnitDevice(analysisLineBatch.getLightRailId(), analysisLineBatch.getLineAliasId(), analysisLineBatch.getStartingMileage(), analysisLineBatch.getEndMileage());


        // 1.3 关联关系-封装1-钢轨,2-曲线,3-竖曲线,4-道岔得单位编号
        for (Map<String, Object> unitDevice : unitDeviceList) {
            unitDeviceTable.put(unitDevice.get("unitCode").toString(), unitDevice);
        }

        //原来单元信息删除
        LambdaQueryWrapper<AnalysisLineBatchUnitDevice> wrapper2 = Wrappers.lambdaQuery();
        wrapper2.eq(AnalysisLineBatchUnitDevice::getAnalysisBatchId, analysisLineBatch.getId());
        unitDeviceService.remove(wrapper2);

        // 1.4 循环分析检查项目
        for (AnalysisLineBatchCheckDataMap checkDataMap : analysisLineBatchCheckDataMapList) {
            // 检查数据类型 1-道岔检查 2-钢轨常规探伤检查 3-曲线钢轨磨耗检查
            // 4-钢轨波磨检查 5-道床检查 6-线路检查
            if ("1" == checkDataMap.getEkType()) {
                //1-道岔检查
                //原来道岔检查单元信息详情删除
                LambdaQueryWrapper<AnalysisLineBatchUnitDeviceTurnoutInfo> wrapper3 = Wrappers.lambdaQuery();
                wrapper3.eq(AnalysisLineBatchUnitDeviceTurnoutInfo::getAnalysisBatchId, analysisLineBatch.getId());
                analysisLineBatchUnitDeviceTurnoutInfoService.remove(wrapper3);
                turnoutCheckDataLineAnalysis(analysisLineBatch, checkDataMap, unitDeviceList);

            } else if ("2" == checkDataMap.getEkType()) {
                //2-钢轨常规探伤检查
                //原来道岔检查单元信息详情删除
                LambdaQueryWrapper<AnalysisLineBatchUnitDeviceRailWearInfo> wrapper3 = Wrappers.lambdaQuery();
                wrapper3.eq(AnalysisLineBatchUnitDeviceRailWearInfo::getAnalysisBatchId, analysisLineBatch.getId());
                analysisLineBatchUnitDeviceRailWearInfoService.remove(wrapper3);
                railWearInfoCheckDataLineAnalysis(analysisLineBatch, checkDataMap, unitDeviceList);

            }
//            else if ("3" == checkDataMap.getEkType()) {
//                //3-曲线钢轨磨耗检查
//                railVehicleCheckDataAnalysis(analysisBatch, checkDataMap, unitDeviceList);
//
//            } else if ("4" == checkDataMap.getEkType()) {
//                //4-钢轨波磨检查
//                addInstrumentAnalysis(analysisBatch, checkDataMap, unitDeviceList);
//            } else if ("5" == checkDataMap.getEkType()) {
//                //5-道床检查
//
//            } else {
//                //6-线路检查
//            }
        }

        // 分析完成ine
        analysisLineBatchService.lambdaUpdate().set(AnalysisLineBatch::getAnalysisStatus, 99).eq(AnalysisLineBatch::getId, analysisLineBatchId).update();
        analysisLineBatchCheckDataMapService.lambdaUpdate().set(AnalysisLineBatchCheckDataMap::getAnalysisStatus, 99).eq(AnalysisLineBatchCheckDataMap::getAnalysisBatchId, analysisLineBatchId).update();
        log.info("[分析完成]|线程id:【" + Thread.currentThread().getId() + "】=============分析批次ID:【" + analysisLineBatchId + "】");
    }

    /**
     * 病害分析->钢轨探伤病害分析批次数据、检查批次、1-钢轨,2-曲线,3-竖曲线,4-道岔
     */
    public void railWearInfoCheckDataLineAnalysis(AnalysisLineBatch analysisLineBatch, AnalysisLineBatchCheckDataMap
            checkDataMap, List<Map<String, Object>> unitDeviceList) {
        //初始化单元表
        List<AnalysisLineBatchUnitDevice> unitList = new ArrayList<>();
        //初始化钢轨探伤病害分析单元表详情
        List<AnalysisLineBatchUnitDeviceRailWearInfo> unitInfoList = new ArrayList<>();
        //获取检查记录详情
        List<RailWearRecord> ekList = railWearRecordService.lambdaQuery().eq(RailWearRecord::getRecordsMasterCheckId, checkDataMap.getEkId()).eq(RailWearRecord::getDelFlag, "0")
                .list();
        //按道岔编号分组检查记录详情
        Map<String, List<RailWearRecord>> deviceProjectList = ekList.stream().collect(Collectors.groupingBy(RailWearRecord::getDeviceProjectCode));
        if (CollectionUtils.isNotEmpty(ekList)) {
            for (Map<String, Object> map : unitDeviceList) {
                //获取分析批次筛选的单元设备编码
                String unitCode = map.get("unitCode").toString();
                //判断分析批次的设备与检查时维护的设备是同一个设备
                List<RailWearRecord> railWearRecordList = deviceProjectList.get(unitCode);
                if (CollectionUtils.isNotEmpty(railWearRecordList)) {
                    String deviceCode = map.get("deviceCode").toString();
                    //保存单元信息
                    String deviceId = saveUnit(analysisLineBatch, checkDataMap, map, unitList, deviceCode);
                    railWearRecordList.forEach(model -> {
                        //保存道岔单元信息详情
                        saveRailWearRecordUnitInfo(analysisLineBatch,checkDataMap,unitInfoList,model,deviceId);
                    });
                }
            }
        }
        if(CollectionUtils.isNotEmpty(unitList)){
            unitDeviceService.saveBatch(unitList);
        }
        if(CollectionUtils.isNotEmpty(unitInfoList)){
            analysisLineBatchUnitDeviceRailWearInfoService.saveBatch(unitInfoList);
        }
    }
    /**
     * 病害分析->道岔病害分析批次数据、检查批次、1-钢轨,2-曲线,3-竖曲线,4-道岔
     */
    public void turnoutCheckDataLineAnalysis(AnalysisLineBatch analysisLineBatch, AnalysisLineBatchCheckDataMap
            checkDataMap, List<Map<String, Object>> unitDeviceList) {
        //初始化单元表
        List<AnalysisLineBatchUnitDevice> unitList = new ArrayList<>();
        //初始化单元表道岔详情
        List<AnalysisLineBatchUnitDeviceTurnoutInfo> unitInfoList = new ArrayList<>();
        //获取检查记录详情
        List<RecordsMasterTurnoutInfo> ekList = turnoutInfoService.lambdaQuery().eq(RecordsMasterTurnoutInfo::getRecordsMasterId, checkDataMap.getEkId()).eq(RecordsMasterTurnoutInfo::getDelFlag, "0")
                .list();
        //按道岔编号分组检查记录详情
        Map<String, List<RecordsMasterTurnoutInfo>> switchCodeList = ekList.stream().collect(Collectors.groupingBy(RecordsMasterTurnoutInfo::getSwitchCode));
        if (CollectionUtils.isNotEmpty(ekList)) {
            for (Map<String, Object> map : unitDeviceList) {
                //获取分析批次筛选的道岔编号
                String deviceCode = map.get("deviceCode").toString();
                //判断分析批次的道岔编号在检查时维护的道岔编号是同一个编号
                List<RecordsMasterTurnoutInfo> recordsMasterTurnoutInfoList = switchCodeList.get(deviceCode);
                if (CollectionUtils.isNotEmpty(recordsMasterTurnoutInfoList)) {
                    //保存单元信息
                    String deviceId = saveUnit(analysisLineBatch, checkDataMap, map, unitList, deviceCode);
                    recordsMasterTurnoutInfoList.forEach(model -> {
                        //保存道岔单元信息详情
                        saveUnitInfo(analysisLineBatch,checkDataMap,unitInfoList,model,deviceId);
                    });
                }
            }
        }
        if(CollectionUtils.isNotEmpty(unitList)){
            unitDeviceService.saveBatch(unitList);
        }
        if(CollectionUtils.isNotEmpty(unitInfoList)){
            analysisLineBatchUnitDeviceTurnoutInfoService.saveBatch(unitInfoList);
        }
    }
//*********************************单元表维护公共方法封装******************************************************************

    /**
     * @param analysisLineBatch 分析主表
     * @param checkDataMap      分析表对应的检查表关系表
     * @param map               分析表内符合的设备信息
     * @param unitList          最终封装到的集合
     * @param switchCode        设备编码
     */
    public String saveUnit(AnalysisLineBatch analysisLineBatch, AnalysisLineBatchCheckDataMap
            checkDataMap, Map<String, Object> map, List<AnalysisLineBatchUnitDevice> unitList, String switchCode) {

        //维护单元表
        AnalysisLineBatchUnitDevice unit = new AnalysisLineBatchUnitDevice();
        unit.setId(UUIDGenerator.generate());
        unit.setAnalysisBatchId(analysisLineBatch.getId());
        unit.setAnalysisBatchCode(analysisLineBatch.getAnalysisBatchCode());
        unit.setEkCode(checkDataMap.getEkCode());
        unit.setEkId(checkDataMap.getEkId());
        unit.setUnitId(map.get("id").toString());
        unit.setUnitCode(map.get("unitCode").toString());
        unit.setUnitType(Integer.valueOf(map.get("type").toString()));
        unit.setUnitTypeName(map.get("typeName").toString());
        unit.setUnitDeviceCode(switchCode);
        unit.setUnitStartMileage(new BigDecimal(map.get("startMileage").toString()));
        unit.setUnitCenterMileage(new BigDecimal(map.get("centerMileage").toString()));
        unit.setUnitEndMileage(new BigDecimal(map.get("endMileage").toString()));
        unit.setWorkStatus(1);
        unit.setRemark(analysisLineBatch.getRemark());
        unitList.add(unit);
        return unit.getId();
    }

    /**
     * @param analysisLineBatch 分析主表
     * @param checkDataMap      分析表对应的检查表关系表
     * @param unitInfoList      最终封装到的集合
     * @param info              检查记录详情
     * @param deviceId          单元表id
     */
    public void saveUnitInfo(AnalysisLineBatch analysisLineBatch, AnalysisLineBatchCheckDataMap
            checkDataMap, List<AnalysisLineBatchUnitDeviceTurnoutInfo> unitInfoList, RecordsMasterTurnoutInfo info, String deviceId) {

        //维护单元详情表
        AnalysisLineBatchUnitDeviceTurnoutInfo unitInfo = new AnalysisLineBatchUnitDeviceTurnoutInfo();
        BeanCopyUtil.copyProperties(info, AnalysisLineBatchUnitDeviceTurnoutInfo.class);
        unitInfo.setId(UUIDGenerator.generate());
        unitInfo.setDeviceId(deviceId);
        unitInfo.setAnalysisBatchId(analysisLineBatch.getId());
        unitInfo.setAnalysisBatchCode(analysisLineBatch.getAnalysisBatchCode());
        unitInfo.setEkCode(checkDataMap.getEkCode());
        unitInfo.setEkId(checkDataMap.getEkId());
        unitInfo.setGaugeCode(masterCheckService.getById(checkDataMap.getEkId()).getGaugeCode());
        unitInfo.setType(info.getType());
        unitInfoList.add(unitInfo);
    }
    /**
     * 钢轨探伤病害分析单元详情维护
     * @param analysisLineBatch 分析主表
     * @param checkDataMap      分析表对应的检查表关系表
     * @param unitInfoList      最终封装到的集合
     * @param info              检查记录详情
     * @param deviceId          单元表id
     */
    public void saveRailWearRecordUnitInfo(AnalysisLineBatch analysisLineBatch, AnalysisLineBatchCheckDataMap
            checkDataMap, List<AnalysisLineBatchUnitDeviceRailWearInfo> unitInfoList, RailWearRecord info, String deviceId) {

        //维护单元详情表
        AnalysisLineBatchUnitDeviceRailWearInfo unitInfo = new AnalysisLineBatchUnitDeviceRailWearInfo();
        BeanCopyUtil.copyProperties(info, AnalysisLineBatchUnitDeviceRailWearInfo.class);
        unitInfo.setId(UUIDGenerator.generate());
        unitInfo.setDeviceId(deviceId);
        unitInfo.setAnalysisBatchId(analysisLineBatch.getId());
        unitInfo.setAnalysisBatchCode(analysisLineBatch.getAnalysisBatchCode());
        unitInfo.setEkCode(checkDataMap.getEkCode());
        unitInfo.setEkId(checkDataMap.getEkId());
        unitInfoList.add(unitInfo);
    }
}
