package com.base.plan.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.base.api.client.SatelliteRpcService;
import com.base.api.client.TragetDemandRpcService;
import com.base.api.model.SatelliteRpcDTO;
import com.base.api.model.TargetDemandRpcDTO;
import com.base.api.model.YxInfoBasisSatelliteRpcDTO;
import com.base.orbit.domain.AjaxResult;
import com.base.orbit.utils.BizUtils;
import com.base.orbit.utils.DateUtils;
import com.base.orbit.utils.IdGenerator;
import com.base.orbit.utils.StringUtils;
import com.base.plan.mapper.*;
import com.base.plan.model.dto.*;
import com.base.plan.model.dto.request.QueryWindowListDTO;
import com.base.plan.model.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author cxl
 * @since 2022-06-24
 */
@Service
@Slf4j
public class AlgSchemeService {

    //  地面站冲突阈值15分钟，中继冲突阈值30分钟
    //    @Value("${target.mutex.station}")
    private Integer stationMutexTime = 900;
    //    @Value("${target.mutex.satellite}")
    //  卫星冲突阈值默认3分钟
    private Integer satelliteMutexTime = 180;

    @Resource
    private AlgSchemeStepMapper algSchemeStepMapper;

    @Resource
    private AlgSchemeStepWindowMapper algSchemeStepWindowMapper;

    @Resource
    private TragetDemandRpcService tragetDemandRpcService;

    @Resource
    private AlgSchemeWindowPassMapper algSchemeWindowPassMapper;

    @Resource
    private StepWindowRelationMapper stepWindowRelationMapper;

    @Resource
    private SatelliteRpcService satelliteRpcService;

    @Resource
    private WindowsMutexCheckBiz windowsMutexCheckBiz;

    @Resource
    private StepWindowDataPassRelationMapper stepWindowDataPassRelationMapper;

    @Resource
    private StepWindowControlPassRelationMapper stepWindowControlPassRelationMapper;

    @Resource
    private StripService stripService;

    public List<StepDTO> getStepList() {
        return copyAlgSchemeStepToStepDTO(algSchemeStepMapper.listNotConfirmAll());
    }

    private List<StepDTO> copyAlgSchemeStepToStepDTO(List<AlgSchemeStep> list) {
        List<StepDTO> res = new ArrayList<>();
        for (AlgSchemeStep AlgSchemeStep : list) {
            StepDTO stepDTO = new StepDTO();
            stepDTO.setId(AlgSchemeStep.getId());
            stepDTO.setSatelliteCount(AlgSchemeStep.getSatCount());
            stepDTO.setStepName(AlgSchemeStep.getStepName());
            stepDTO.setResolvingPower(AlgSchemeStep.getMinLoadResolution() + "-" + AlgSchemeStep.getMaxLoadResolution());
            stepDTO.setObservationMeans(AlgSchemeStep.getLoadType());
            stepDTO.setTotalTimes(AlgSchemeStep.getObserveNum().intValue());
            if (AlgSchemeStep.getDaily() != null) {
                stepDTO.setRateDay(AlgSchemeStep.getDaily().floatValue());
            } else {
                stepDTO.setRateDay(0.0F);
            }
            stepDTO.setEarliestObservationTime(AlgSchemeStep.getEarliestObservationTime());
            if (AlgSchemeStep.getMaxScoutFre() != null) {
                stepDTO.setMaximumInterval(AlgSchemeStep.getMaxScoutFre().toString());
            } else {
                stepDTO.setMaximumInterval("");
            }
            if (AlgSchemeStep.getMinScoutFre() != null) {
                stepDTO.setMinimumInterval(AlgSchemeStep.getMinScoutFre().toString());
            } else {
                stepDTO.setMinimumInterval("");
            }
            stepDTO.setPriority(AlgSchemeStep.getPriority());
            res.add(stepDTO);
        }
        return res;
    }

    /**
     * 通过需求窗口关系表查询
     *
     * @return
     */
    public List<StepDetailDTO> getIsUsedStepDetailList() {
        //  获取评估方案下所有的条带窗口
        List<StepWindowRelation> stepWindowRelationList = stepWindowRelationMapper.selectList(new QueryWrapper<>());
        if (CollectionUtils.isEmpty(stepWindowRelationList)) {
            return new ArrayList<>();
        }
        //  挑选已被确认的条带(分析结果窗口中界面确认选择的条带)
        List<StepWindowRelation> stepWindowRelations = stepWindowRelationList.stream().filter(stepWindowRelation -> stepWindowRelation.getIsConfirm().equals(2)).collect(Collectors.toList());
        //  根据窗口id查询所有方案(条带)
        List<AlgSchemeStepWindow> list = algSchemeStepWindowMapper.selectBatchIds(stepWindowRelations.stream().map(StepWindowRelation::getWindowId).collect(Collectors.toList()));
        return getStepDetailList(list);
    }

    /**
     * 需求解译中确认的条带，对应生成的方案
     *
     * @param list
     * @return
     */
    public List<StepDetailDTO> getStepDetailList(List<AlgSchemeStepWindow> list) {
        Set<String> parentIds = list.stream().map(AlgSchemeStepWindow::getParentId).collect(Collectors.toSet());
        Set<String> windowIds = list.stream().map(AlgSchemeStepWindow::getId).collect(Collectors.toSet());
        List<String> satelliteIds = list.stream().map(AlgSchemeStepWindow::getSatelliteId).collect(Collectors.toList());

        //  1.根据需求批次号查询观测目标
        List<TargetDemandRpcDTO> targetDemandRpcDTOS = tragetDemandRpcService.selTargetDemandByParentId(parentIds);
        if (CollectionUtils.isEmpty(targetDemandRpcDTOS) || CollectionUtils.isEmpty(satelliteIds))
            return new ArrayList<>();
        //  2.去重查询,根据卫星id查询卫星信息
        List<String> newSatelliteIds = satelliteIds.stream().distinct().collect(Collectors.toList());
        List<SatelliteRpcDTO> satelliteRpcDTOS = satelliteRpcService.queryAllSatelliteByIds(newSatelliteIds);
//        List<SatelliteRpcDTO> satelliteRpcDTORmEle = rmDuplicateHashSet(satelliteRpcDTOS);
        //  3.根据条带id查询该条带配置的测控\数传窗口
        List<AlgSchemeWindowPass> algSchemeWindowPasses = algSchemeWindowPassMapper.selectAlgSchemeWindowPassListByWindowIds(windowIds, null);
        List<StepDetailDTO> stepDetailDTOS = copyAlgSchemeStepWindowToStepDetailDTO(list, targetDemandRpcDTOS, satelliteRpcDTOS, algSchemeWindowPasses);
        stepDetailDTOS = stepDetailDTOS.stream().sorted(Comparator.comparing(StepDetailDTO::getParentId)).collect(Collectors.toList());
        return stepDetailDTOS;
    }

    /**
     * 通过HashSet去重
     *
     * @param list
     * @return
     */
    public static <T> List<T> rmDuplicateHashSet(List<T> list) {
        HashSet<T> hs = new HashSet<>(list);
        list.clear();
        list.addAll(hs);
        return list;
    }

    /**
     * 条带匹配合适进出站弧段组成复合结果返回
     *
     * @param list                  条带集合
     * @param yxTargetRelations     观测区域
     * @param satelliteRpcDTOS      卫星信息
     * @param algSchemeWindowPasses 进出站弧段
     * @return
     */
    private List<StepDetailDTO> copyAlgSchemeStepWindowToStepDetailDTO(List<AlgSchemeStepWindow> list, List<TargetDemandRpcDTO> yxTargetRelations, List<SatelliteRpcDTO> satelliteRpcDTOS, List<AlgSchemeWindowPass> algSchemeWindowPasses) {
        List<StepDetailDTO> res = new ArrayList<>();
        //  查询所有条带，获取条带选中状态
        List<StripInfo> stripInfos = stripService.list();
        //  1.遍历筹划方案，构建StepDetailDTO对象
        for (AlgSchemeStepWindow algSchemeStepWindow : list) {
            StepDetailDTO stepDTO = new StepDetailDTO();
            stepDTO.setStepId(algSchemeStepWindow.getSchemeStepId());
            stepDTO.setParentId(algSchemeStepWindow.getParentId());
            stepDTO.setWindowId(algSchemeStepWindow.getId());
            stepDTO.setStripStartTime(algSchemeStepWindow.getStartTime());
            stepDTO.setStripEndTime(algSchemeStepWindow.getEndTime());
            //  2.根据需求批次号查询目标，获取目标名称
            Optional<TargetDemandRpcDTO> optionalYxTargetRelation = yxTargetRelations.stream().filter(e -> e.getParentId().equals(algSchemeStepWindow.getParentId().replace("[", "").replace("]", "").trim())).findFirst();
            if (optionalYxTargetRelation.isPresent()) {
                stepDTO.setTargetName(optionalYxTargetRelation.get().getTargetName());
            } else {
                stepDTO.setTargetName("");
            }
            //  3.根据卫星id查询卫星信息，获取卫星名称和载荷类型
            Optional<SatelliteRpcDTO> optionalYxInfoBasisSatellite = satelliteRpcDTOS.stream().filter(e -> e.getId().equals(algSchemeStepWindow.getSatelliteId())).findFirst();
            if (optionalYxInfoBasisSatellite.isPresent()) {
                stepDTO.setSatelliteName(optionalYxInfoBasisSatellite.get().getSatelliteName());
                stepDTO.setSatelliteCode(optionalYxInfoBasisSatellite.get().getSatelliteCode());
                stepDTO.setLoadType(optionalYxInfoBasisSatellite.get().getLoadType());
            } else {
                stepDTO.setSatelliteName("");
            }
            //  4.根据条带id匹配测控\数传窗口
            List<AlgSchemeWindowPass> windowPassList = algSchemeWindowPasses.stream().filter(e -> e.getSchemeStepWindowId().equals(algSchemeStepWindow.getId())).collect(Collectors.toList());
            //  5.测控窗口(默认挑选符合条件的第一个站)
            Optional<AlgSchemeWindowPass> optionalAlgSchemeWindowPass = windowPassList.stream().filter(e -> e.getPassType() != null).filter(e -> e.getPassType() == 1).findFirst();
            if (optionalAlgSchemeWindowPass.isPresent()) {
                stepDTO.setControlStationName(optionalAlgSchemeWindowPass.get().getStationName());
                stepDTO.setControlStartTime(optionalAlgSchemeWindowPass.get().getStartTime());
                stepDTO.setControlEndTime(optionalAlgSchemeWindowPass.get().getEndTime());
                stepDTO.setControlStationCode(optionalAlgSchemeWindowPass.get().getStationCode());
                //  确定测控窗口后，需将窗口确认状态改为已确认  stepDTO.id ->step_window_control_pass_relation.control_station_window_id && stepDTO.schemeStepWindowId->window_id

            } else {
                //  条带如果未找到，合适的测控\数传资源，系统重新挑选条带
            }
            stepDTO.setAccessTime(algSchemeStepWindow.getAccessTime());
            stepDTO.setAccessDuration(String.valueOf(DateUtils.getDatePoor(algSchemeStepWindow.getEndTime(), algSchemeStepWindow.getStartTime())));
            //  6.数传窗口(默认挑选符合条件的第一个站)
            Optional<AlgSchemeWindowPass> optionalDataAlgSchemeWindowPass = windowPassList.stream().filter(e -> e.getPassType() == 2).findFirst();
            if (optionalDataAlgSchemeWindowPass.isPresent()) {
                stepDTO.setDataStationName(optionalDataAlgSchemeWindowPass.get().getStationName());
                stepDTO.setDataStartTime(optionalDataAlgSchemeWindowPass.get().getStartTime());
                stepDTO.setDataEndTime(optionalDataAlgSchemeWindowPass.get().getEndTime());
                stepDTO.setDataStationCode(optionalDataAlgSchemeWindowPass.get().getStationCode());
                //  确定数传窗口后，需将窗口确认状态改为已确认  stepDTO.id ->step_window_data_pass_relation.data_station_window_id && stepDTO.schemeStepWindowId->window_id
//                stepWindowDataPassRelationMapper.validateWindow(optionalDataAlgSchemeWindowPass.get());
            } else {

            }
            Optional<StripInfo> stripInfoOptional = stripInfos.stream().filter(stripInfo -> stripInfo.getWindowId().equals(algSchemeStepWindow.getId())).findFirst();
            if (stripInfoOptional.isPresent()) {
                StripInfo stripInfo = stripInfoOptional.get();
                stepDTO.setIsSelected(stripInfo.getIsSelected());
            }
            stepDTO.setResolvingPower(algSchemeStepWindow.getResolvingPower().floatValue());
            stepDTO.setSideSwayValue(algSchemeStepWindow.getSideSwayValue().toString());
            stepDTO.setClothWith(algSchemeStepWindow.getClothWith().toString());
            stepDTO.setCoverage(algSchemeStepWindow.getCoverage());
            stepDTO.setPitchAngle(algSchemeStepWindow.getPitchAngle());
            stepDTO.setWindowId(algSchemeStepWindow.getId());



            res.add(stepDTO);
        }
        //  7.返回筹划方案应是不同观测卫星选取条带或是同颗星不同的圈号条带所形成的方案
        return res;
    }

    /**
     * 重组筹划方案结果
     *
     * @param list                  筹划方案
     * @param stepWindowRelationSet 已确认的窗口
     * @return
     */
    public List<StripReqDTO> getWindowDTOList(List<StepDetailDTO> list, Set<String> stepWindowRelationSet) {

        //  通过窗口id查询条带获取圈号
        List<String> windowIds = list.stream().map(StepDetailDTO::getWindowId).collect(Collectors.toList());
        QueryWrapper<StripInfo> stripInfoQueryWrapper = new QueryWrapper<>();
        stripInfoQueryWrapper.in("window_id", windowIds);
        List<StripInfo> stripInfos = stripService.list(stripInfoQueryWrapper);
        List<WindowDTO> res = new ArrayList<>();
        for (StepDetailDTO stepDetailDTO : list) {
            WindowDTO windowDTO = new WindowDTO();
            windowDTO.setId(stepDetailDTO.getWindowId());
            windowDTO.setSatelliteName(stepDetailDTO.getSatelliteName());
            windowDTO.setSideSwayValue(stepDetailDTO.getSideSwayValue());
            windowDTO.setIsSelected(stepDetailDTO.getIsSelected());
            windowDTO.setAccessTime(stepDetailDTO.getAccessTime());
            windowDTO.setCoverage(stepDetailDTO.getCoverage().toString());
            windowDTO.setAccessDuration(stepDetailDTO.getAccessDuration());
            windowDTO.setPitchAngle(Objects.isNull(stepDetailDTO.getPitchAngle()) ? "" : stepDetailDTO.getPitchAngle().toString());
            windowDTO.setResolvingPower(stepDetailDTO.getResolvingPower());
            windowDTO.setLoadType(stepDetailDTO.getLoadType());
            //  设置圈号（条带与筹划方案 一对一，故直接取值）
            Optional<StripInfo> stripInfoOptional = stripInfos.stream().filter(stripInfo -> stripInfo.getWindowId().equals(stepDetailDTO.getWindowId())).findFirst();
            if (stripInfoOptional.isPresent()) {
                StripInfo stripInfo = stripInfoOptional.get();
                windowDTO.setCircle(stripInfo.getCircle());
                windowDTO.setObservationStartTime(stripInfo.getObservationStartTime());
                windowDTO.setObservationEndTime(stripInfo.getObservationEndTime());
                windowDTO.setGroundResolution(stripInfo.getGroundResolution());
                windowDTO.setStripId(stripInfo.getId());
            }
            if (CollectionUtils.isEmpty(stepWindowRelationSet)) {
                res.add(windowDTO);
                continue;
            }
            if (stepWindowRelationSet.contains(stepDetailDTO.getWindowId())) {
                windowDTO.setIsUsed(1);
            } else {
                windowDTO.setIsUsed(2);
            }
            res.add(windowDTO);
        }
        return castStripDTOList(res);
    }


    /**
     * 根据圈号进行分组
     * <p>
     * 返回数据结构卫星-圈号，条带查询时按照此结构返回，所以此处直接复用之前代码
     *
     * @param windowDTOs
     * @return
     */
    public List<StripReqDTO> castStripDTOList(List<WindowDTO> windowDTOs) {
        List<StripReqDTO> stripReqDTOS = new ArrayList<>();
        List<StripInfo> stripInfoList = new ArrayList<>();
        for (WindowDTO windowDTO : windowDTOs) {
            StripInfo stripInfo = new StripInfo();
            stripInfo.setSatelliteCode(windowDTO.getSatelliteName());
            stripInfo.setRollAngle(windowDTO.getSideSwayValue());
            stripInfo.setCoverageRate(windowDTO.getCoverage());
            stripInfo.setPitchAngle(!StringUtils.isEmpty(windowDTO.getPitchAngle()) ? Double.valueOf(windowDTO.getPitchAngle()) : null);
            stripInfo.setObservationStartTime(windowDTO.getObservationStartTime());
            stripInfo.setObservationEndTime(windowDTO.getObservationEndTime());
            stripInfo.setCircle(windowDTO.getCircle());
            stripInfo.setGroundResolution(windowDTO.getGroundResolution());
            stripInfo.setId(windowDTO.getStripId());
            stripInfo.setIsSelected(windowDTO.getIsUsed());
            stripInfo.setWindowId(windowDTO.getId());
            stripInfo.setIsSelected(windowDTO.getIsSelected());
            stripInfoList.add(stripInfo);
        }
        //  根据卫星圈号分组
        Map<String, List<StripInfo>> circleMap = stripInfoList.stream().collect(
                Collectors.groupingBy(stripReqDTO ->
                        stripReqDTO.getSatelliteCode() + "-" + stripReqDTO.getCircle()));

        for (Map.Entry<String, List<StripInfo>> entry : circleMap.entrySet()) {
            String key = entry.getKey();
            StripReqDTO stripReqDTO = new StripReqDTO();
            String[] keystr = key.split("-");
            String SatelliteCode = "";
            String Circle = "";
            if (keystr.length >= 3) {
                SatelliteCode = keystr[0] + "-" + keystr[1];
                Circle = keystr[2];
            } else {
                SatelliteCode = keystr[0];
                Circle = keystr[1];
            }
            stripReqDTO.setSatelliteCode(SatelliteCode);
            stripReqDTO.setCircle(Circle);
            List<StripInfo> stripInfos = entry.getValue();
            List<StripDTO> stripDTOS = BizUtils.copyEntityToDto(StripDTO.class, stripInfos);

            stripDTOS.stream().forEach(stripDTO -> {
                        //   取中间时刻
                        long time = (stripDTO.getObservationEndTime().getTime() + stripDTO.getObservationStartTime().getTime()) / 2;
                        stripDTO.setAccessTime(new Date(time));
                        stripDTO.setDuration((stripDTO.getObservationEndTime().getTime() - stripDTO.getObservationStartTime().getTime()) / 1000);
                        stripDTO.setCoverageRate(stripDTO.getCoverageRate());
                        Optional<StripInfo> stripInfoOptional = stripInfos.stream().filter(stripInfo -> stripInfo.getId().equals(stripDTO.getId())).findFirst();
                        if (stripInfoOptional.isPresent()) {
                            StripInfo stripInfo = stripInfoOptional.get();
                            stripDTO.setIsUsed(stripInfo.getIsSelected());
                            stripDTO.setWindowId(stripInfo.getWindowId());
                        }
                    }
            );

            stripReqDTO.setStripRollAngleDTOS(stripDTOS);
            stripReqDTOS.add(stripReqDTO);
            //  根据卫星编号排序
            stripReqDTOS = stripReqDTOS.stream().sorted(Comparator.comparing(StripReqDTO::getSatelliteCode)).collect(Collectors.toList());
        }
        return stripReqDTOS;
    }


    public List<StripReqDTO> getWindowList(QueryWindowListDTO queryWindowListDTO) {
        //  1.根据筹划方案生成方案结果
        List<StepDetailDTO> list = getStepDetailList(algSchemeStepWindowMapper.getWindowList(queryWindowListDTO));
        //  2.该方案下中已经选取的窗口
        Set<String> stepWindowRelationSet = stepWindowRelationMapper.selectByStepId(queryWindowListDTO.getStepId(), 2).stream().map(StepWindowRelation::getWindowId).collect(Collectors.toSet());
        Assert.isTrue(!Objects.isNull(stepWindowRelationSet), "需求id[" + queryWindowListDTO.getStepId() + "]不存在挑选确认窗口");
        return getWindowDTOList(list, stepWindowRelationSet);
    }

    public AjaxResult taskMonitor(QueryWindowListDTO queryWindowListDTO) {
        List<StepWindowRelation> stepWindowRelationList = stepWindowRelationMapper.selectList(new QueryWrapper<>());
        if (CollectionUtils.isEmpty(stepWindowRelationList)) {
            return AjaxResult.error();
        }
        //  挑选已被确认的条带(分析结果窗口中界面确认选择的条带)
        List<StepWindowRelation> stepWindowRelations = stepWindowRelationList.stream().filter(stepWindowRelation -> stepWindowRelation.getIsConfirm().equals(2)).collect(Collectors.toList());
        List<String> windowIds = stepWindowRelations.stream().map(StepWindowRelation::getWindowId).collect(Collectors.toList());
        List<AlgSchemeStepWindow> algSchemeStepWindowMapperWindowList = algSchemeStepWindowMapper.getWindowList(queryWindowListDTO);
        List<AlgSchemeStepWindow> algSchemeStepWindows = algSchemeStepWindowMapperWindowList.stream().filter(algSchemeStepWindowMapperWindow ->
                windowIds.contains(algSchemeStepWindowMapperWindow.getId())).collect(Collectors.toList());
        List<StepDetailDTO> stepDetailDTOS = getStepDetailList(algSchemeStepWindows);
        if (!CollectionUtils.isEmpty(stepDetailDTOS)) {
            return AjaxResult.success(stepDetailDTOS);
        }
        return AjaxResult.error();
    }


    public List<PassDTO> getPassList(QueryPassDTO reqDTO) {
        Set<String> set = null;
        if (!StringUtils.isEmpty(reqDTO.getWindowIds())) {
            set = new HashSet<>(Arrays.asList(reqDTO.getWindowIds().split(",")));
        } else {
            set = new HashSet<>();
        }
        //  根据可见窗口id查询对应测控\数传列表
        List<AlgSchemeWindowPass> list = algSchemeWindowPassMapper.selectAlgSchemeWindowPassListByWindowIds(set, reqDTO.getPassType());
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        //  方案id集合
        Set<String> ids = list.stream().map(AlgSchemeWindowPass::getSchemeStepWindowId).collect(Collectors.toSet());
        //  获取该条带窗口已确认的数传弧段id
        Set<String> checkDataIsUsedSet = stepWindowDataPassRelationMapper.selectByWindowId(ids).stream().map(StepWindowDataPassRelation::getDataStationWindowId).collect(Collectors.toSet());
        //  获取该条带窗口已确认的测控弧段id
        Set<String> checkControlIsUsedSet = stepWindowControlPassRelationMapper.selectByWindowId(ids).stream().map(StepWindowControlPassRelation::getControlStationWindowId).collect(Collectors.toSet());
        List<SatelliteRpcDTO> satelliteRpcDTOS = satelliteRpcService.queryAllSatelliteByIds(list.stream().map(AlgSchemeWindowPass::getSatelliteId).collect(Collectors.toList()));
        List<PassDTO> res = new ArrayList<>();
        for (AlgSchemeWindowPass algSchemeWindowPass : list) {
            PassDTO passDTO = new PassDTO();
            passDTO.setId(algSchemeWindowPass.getId());
            passDTO.setWindowId(algSchemeWindowPass.getSchemeStepWindowId());
            passDTO.setPassType(algSchemeWindowPass.getPassType());
            Optional<SatelliteRpcDTO> yxInfoBasisSatellite = satelliteRpcDTOS.stream().filter(e -> e.getId().equals(algSchemeWindowPass.getSatelliteId())).findFirst();
            if (yxInfoBasisSatellite.isPresent()) {
                passDTO.setSatelliteCode(yxInfoBasisSatellite.get().getSatelliteCode());
            } else {
                passDTO.setSatelliteCode("");
            }
            passDTO.setCircleNumber(algSchemeWindowPass.getPassNum().toString());
            passDTO.setStartTime(algSchemeWindowPass.getStartTime());
            passDTO.setDuration(((algSchemeWindowPass.getEndTime().getTime() - algSchemeWindowPass.getStartTime().getTime()) / 1000) + "");
            passDTO.setStationCode(algSchemeWindowPass.getStationName());
            passDTO.setPassStatus(Integer.parseInt(algSchemeWindowPass.getPassStatus()));
            passDTO.setIsDefalut(algSchemeWindowPass.getIsDefalut());

            //  设置测控站使用状态
            if (algSchemeWindowPass.getPassType() == 1) {
                if (checkControlIsUsedSet.contains(algSchemeWindowPass.getId())) {
                    passDTO.setIsUsed(1);
                } else {
                    passDTO.setIsUsed(2);
                }
            } else {
                //  数传站使用状态
                if (checkDataIsUsedSet.contains(algSchemeWindowPass.getId())) {
                    passDTO.setIsUsed(1);
                } else {
                    passDTO.setIsUsed(2);
                }
            }
            res.add(passDTO);
        }
        return res;
    }


    public void batchAlgSchemeWindowPass(List<AlgSchemeWindowPass> windowPasses) {
        algSchemeWindowPassMapper.batchAlgSchemeWindowPass(windowPasses);
    }

    /**
     * 数传窗口冲突检测
     *
     * @return 数传窗口冲突数据
     */

    public List<List<StationMutexDTO>> getStationMutexDTOList(List<String> list) {
        List<List<StationMutexDTO>> res = new ArrayList<>();
        List<StepWindowDTO> stepWindowDTOList = stepWindowDataPassRelationMapper.selectIsUsedStepStationWindowDTOList(list, 2);
        if (CollectionUtils.isEmpty(stepWindowDTOList)) {
            return res;
        }
        List<SatelliteRpcDTO> satellites = satelliteRpcService.queryAllSatelliteByIds(stepWindowDTOList.stream().map(StepWindowDTO::getSatelliteId).collect(Collectors.toList()));
        if (CollectionUtils.isEmpty(satellites)) return new ArrayList<>();
        stepWindowDTOList.forEach(e -> e.setUniqueKey(e.getStationId()));
        Map<String, List<StepWindowDTO>> map = windowsMutexCheckBiz.getMutexList(1, stepWindowDTOList, stationMutexTime, stationMutexTime);
        for (StepWindowDTO stepWindowDTO : stepWindowDTOList) {
            String stationWindowId = stepWindowDTO.getStationWindowId();
            String code = stepWindowDTO.getUniqueKey();
            formatSatelliteMutexDTOListRes(map, stationWindowId, code, satellites, res, 2);
        }
        return res;
    }


    public List<List<SatelliteMutexDTO>> getSatelliteMutexDTOList(List<String> list) {
        List<List<SatelliteMutexDTO>> res = new ArrayList<>();
        //联查已经选中的需求和侦察窗口
        List<StepWindowDTO> stepWindowDTOList = stepWindowRelationMapper.selectIsUsedStepWindowDTOList(list, 2);
        if (CollectionUtils.isEmpty(stepWindowDTOList)) {
            return res;
        }
        List<SatelliteRpcDTO> satellites = satelliteRpcService.queryAllSatelliteByIds(stepWindowDTOList.stream().map(StepWindowDTO::getSatelliteId).collect(Collectors.toList()));
        stepWindowDTOList.forEach(e -> e.setUniqueKey(e.getSatelliteId()));
        //key是窗口的id
        //todo 前置时间和后置时间根据配置文件进行取值，因不同的星拍摄装置调整时间不同
        Map<String, List<StepWindowDTO>> map = windowsMutexCheckBiz.getMutexList(2, stepWindowDTOList, satelliteMutexTime, satelliteMutexTime);
        //根据需求来标识冲突
        for (StepWindowDTO stepWindowDTO : stepWindowDTOList) {
            String code = stepWindowDTO.getUniqueKey();
            String windowId = stepWindowDTO.getWindowId();
            formatSatelliteMutexDTOListRes(map, windowId, code, satellites, res, 1);
        }
        return res;
    }

    private <T> void formatSatelliteMutexDTOListRes(Map<String, List<StepWindowDTO>> map, String windowId, String code, List<SatelliteRpcDTO> satellites, List<List<T>> res, Integer type) {

        if (map.containsKey(code)) {
            List<StepWindowDTO> list = map.get(code);
            //获取窗口的位置,窗口肯定是唯一的，所以直接获取最后一个
            Optional<StepWindowDTO> optionalStepWindowDTO = list.stream().filter(e -> (type == 1 ? e.getWindowId() : e.getStationWindowId()).equals(windowId)).findFirst();
            if (optionalStepWindowDTO.isPresent()) {
                //  获取指定元素出现的最后一个索引，比如:[1,2,4,5,2]  2元素指定最后一个索引为4
                int index = list.lastIndexOf(optionalStepWindowDTO.get());
                //  交换集合中元素的位置，将指定窗口调换至第一个元素
                Collections.swap(list, 0, index);
                List<T> satelliteMutexDTOList = new ArrayList<>();
                T[] t = (T[]) new Object[1];
                for (StepWindowDTO stepWindowDTO : list) {
                    if (type == 1) {
                        t[0] = (T) new SatelliteMutexDTO();
                    } else if (type == 2) {
                        t[0] = (T) new StationMutexDTO();
                    }
                    BeanUtils.copyProperties(stepWindowDTO, t[0]);
                    Field[] field = new Field[1];
                    try {
                        field[0] = t[0].getClass().getField("satelliteCode");
                        //  绕过权限控制检查，私有属性也能获取
                        field[0].setAccessible(true);
                    } catch (NoSuchFieldException e) {
                        log.error(e.getMessage(), e);
                    }
                    satellites.stream().filter(e -> e.getId().equals(stepWindowDTO.getSatelliteId())).findFirst().ifPresent(yxInfoBasisSatellite -> {
                        try {
                            //  指定对象参数设置新值
                            field[0].set(t[0], yxInfoBasisSatellite.getSatelliteCode());
                            satelliteMutexDTOList.add(t[0]);
                        } catch (IllegalAccessException e) {
                            log.error(e.getMessage(), e);
                        }
                    });

                }
                res.add(satelliteMutexDTOList);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateWindowList(List<QueryUpdateWindowDTO> reqDTO) {
        if (CollectionUtils.isEmpty(reqDTO)) {
            return;
        }
        List<String> stepIds = new ArrayList<>();
        List<StepWindowRelation> addWindowIds = new ArrayList<>();
        List<StepWindowDataPassRelation> addStations = new ArrayList<>();
        reqDTO.forEach(e -> stepIds.add(e.getStepId()));
        //先删除
        stepWindowRelationMapper.deleteByStepIds(stepIds);
        stepWindowDataPassRelationMapper.deleteByStepIds(stepIds);
        //再新增
        for (QueryUpdateWindowDTO queryUpdateWindowDTO : reqDTO) {
            for (WindowAndDataWindowRelationDTO windowAndDataWindowRelationDTO : queryUpdateWindowDTO.getWindowRelationDTOList()) {
                StepWindowRelation stepWindowRelation = new StepWindowRelation();
                stepWindowRelation.setId(IdGenerator.getId());
                stepWindowRelation.setWindowId(windowAndDataWindowRelationDTO.getWindowId());
                stepWindowRelation.setStepId(queryUpdateWindowDTO.getStepId());
                stepWindowRelation.setCreateTime(new Date());
                stepWindowRelation.setIsConfirm(2);
                addWindowIds.add(stepWindowRelation);

                StepWindowDataPassRelation stepWindowDataPassRelation = new StepWindowDataPassRelation();
                stepWindowDataPassRelation.setId(IdGenerator.getId());
                stepWindowDataPassRelation.setStepId(queryUpdateWindowDTO.getStepId());
                stepWindowDataPassRelation.setWindowId(windowAndDataWindowRelationDTO.getWindowId());
                stepWindowDataPassRelation.setDataStationWindowId(windowAndDataWindowRelationDTO.getDataWindowId());
                stepWindowDataPassRelation.setCreateTime(new Date());
                addStations.add(stepWindowDataPassRelation);
            }
        }
        if (!CollectionUtils.isEmpty(addStations)) {
            stepWindowRelationMapper.batchInsert(addWindowIds);
        }
        if (!CollectionUtils.isEmpty(addStations)) {
            stepWindowDataPassRelationMapper.batchInsert(addStations);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void confirmScheme(List<String> stepIds) {
        algSchemeStepMapper.confirmScheme(stepIds);
        stepWindowRelationMapper.confirmWindow(stepIds);
        stepWindowControlPassRelationMapper.confirmWindow(stepIds);
        stepWindowDataPassRelationMapper.confirmWindow(stepIds);
    }
}
