/*
 * Author: Zev
 * 生成ServiceImpl
 */
package com.tofly.gpsboot.service.paln.task.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tofly.api.DepartmentClient;
import com.tofly.common.core.util.DateUtil;
import com.tofly.common.oauth.util.SecurityUtils;
import com.tofly.gpsboot.common.Constant;
import com.tofly.gpsboot.common.system.*;
import com.tofly.gpsboot.exception.BusinessException;
import com.tofly.gpsboot.mapper.plan.PlanMapper;
import com.tofly.gpsboot.service.comm.IDisposeDateService;
import com.tofly.gpsboot.service.config.InspecttypeService;
import com.tofly.gpsboot.service.config.PeriodService;
import com.tofly.gpsboot.service.mq.IPlanMessageService;
import com.tofly.gpsboot.service.paln.HydrantrecordService;
import com.tofly.gpsboot.service.paln.LeakRecordService;
import com.tofly.gpsboot.service.paln.PlantypeService;
import com.tofly.gpsboot.service.paln.task.*;
import com.tofly.gpsboot.service.process.PiperecordService;
import com.tofly.gpsboot.service.process.PointtempService;
import com.tofly.gpsboot.service.process.PressrecordService;
import com.tofly.gpsboot.service.process.RecordService;
import com.tofly.gpsboot.service.sign.PdasignService;
import com.tofly.gpsboot.util.DateTimeUtil;
import com.tofly.pojo.User;
import com.tofly.pojo.plan.*;
import com.tofly.pojo.plan.dto.PlanDto;
import com.tofly.pojo.plan.vo.PlanDetailVo;
import com.tofly.pojo.plan.vo.PlanVo;
import com.tofly.pojo.plan.vo.PlanchildVo;
import com.tofly.pojo.plan.vo.RecordVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 巡检计划详细信息表：TF_YWPN__PLAN_W
 *
 * @author admin
 * @date Thu Mar 18 00:00:00 CST 2021
 */
@Service("planService")
@Slf4j
public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements PlanService {

    @Autowired
    private PeriodService periodService;

    @Autowired
    private PlanInspectGroupService planInspectGroupService;

    @Autowired
    private PlanInspectUserService planInspectUserService;

    @Autowired
    private InspecttypeService inspecttypeService;

    @Autowired
    private PointtempService pointtempService;

    @Autowired
    private PlanchildService planchildService;

    @Autowired
    private PdasignService pdasignService;

    @Autowired
    private IPlanMessageService iPlanMessageService;

    @Autowired
    private PlanstopService planstopService;

    @Autowired
    private PlancancleService plancancleService;

    @Autowired
    private DepartmentClient departmentClient;
    @Autowired
    private IDisposeDateService iDisposeDateService;

    @Autowired
    private RecordService recordService;
    @Autowired
    private PressrecordService pressrecordService;

    @Autowired
    private PiperecordService piperecordService;

    @Autowired
    private HydrantrecordService hydrantrecordService;

    @Autowired
    private LeakRecordService leakRecordService;

    @Autowired
    private PlantypeService plantypeService;

    @Autowired
    private PlanFactoryService planFactoryService;

    @Override
    public List<PlanVo> viewConversion(List<Plan> infoList) {
        List<PlanVo> planVoList = new LinkedList<>();
        infoList.forEach(info -> {
            PlanVo baseInfo = JSON.parseObject(JSON.toJSONString(info), PlanVo.class);
            String inspectType = info.getInspectType();
            // 处理巡检类型
            if (!StringUtils.isEmpty(inspectType)) {
                List<Long> longList = Arrays.stream(inspectType.split(Constant.CSV)).map(s -> Long.parseLong(s.trim()))
                        .collect(Collectors.toList());
                baseInfo.setInspectTypeName(inspecttypeService.getInspectTypeName(longList));
            }
            baseInfo.setIsread(IsReadEnum.getCodeForValue(info.getIsread()));
            baseInfo.setIsover(IsOverEnum.getCodeForValue(info.getIsover()));
            baseInfo.setPlanState(PlanStateEnum.getCodeForValue(info.getPlanState()));
            baseInfo.setInspectGroupId(planInspectGroupService.getInspectGroupId(info.getId()));
            baseInfo.setInspectGroup(planInspectGroupService.getInspectGroupName(info.getId()));
            baseInfo.setInspectUsers(planInspectUserService.getInspectUserIdList(info.getId()));
            baseInfo.setInspectUserList(planInspectUserService.getInspectUserList(info.getId()));
            baseInfo.setIsDispatchingName(IsDispatchingEnum.getCodeForValue(info.getIsDispatching()));
            Long periodId = info.getPeriodId();
            if (null != periodId) {
                baseInfo.setPeriodIdName(periodService.getById(periodId).getPeriodName());
            }
            // 查询当前计划是否暂停/作废
            List<Planstop> list = planstopService.list(new QueryWrapper<Planstop>().lambda().eq(Planstop::getPlanId, info.getId()));
            if (null != list && list.size() > 0) {
                String auditResult = list.get(0).getAuditResult();
                if (IsAuditEnum.IS_AUDIT_YES.getCode().equals(auditResult)) {
                    baseInfo.setIsPlanStop(IsRespectEnum.IS_RESPECT_YES.getValue());
                } else {
                    baseInfo.setIsPlanStop(IsRespectEnum.IS_RESPECT_NO.getValue());
                }
            } else {
                baseInfo.setIsPlanStop(IsRespectEnum.IS_RESPECT_NO.getValue());
            }
            List<Plancancle> plancancleList = plancancleService.list(new QueryWrapper<Plancancle>().lambda().eq(Plancancle::getPlanId, info.getId()));
            if (null != plancancleList && plancancleList.size() > 0) {
                String auditResult = plancancleList.get(0).getAuditResult();
                if (IsAuditEnum.IS_AUDIT_YES.getCode().equals(auditResult)) {
                    baseInfo.setIsPlanInvalid(IsRespectEnum.IS_RESPECT_YES.getValue());
                } else {
                    baseInfo.setIsPlanInvalid(IsRespectEnum.IS_RESPECT_NO.getValue());
                }
            } else {
                baseInfo.setIsPlanInvalid(IsRespectEnum.IS_RESPECT_NO.getValue());
            }

            baseInfo.setPlanFactoryList(planFactoryService.list(new QueryWrapper<PlanFactory>().lambda().eq(PlanFactory::getPlanId, info.getId())));
            baseInfo.setPlanTypeOverList(plantypeService.list(new QueryWrapper<Plantype>().lambda().eq(Plantype::getPlanId, info.getId())));
            planVoList.add(baseInfo);
        });
        return planVoList;
    }


    @Override
    public Page<PlanVo> getPlanPage(Page page, PlanDto dto) {
        // 获取前端传入部门id
        Long deptId = dto.getDeptId();
        // 是否跨部门
        Set<Long> userIdList = departmentClient.getDeptUserList(String.valueOf(null == deptId ? SecurityUtils.getUser().getDepartmentId() : deptId)).getResult().stream().map(User::getId).collect(Collectors.toSet());
        if (StringUtils.isEmpty(dto.getFlag())) {
            if (userIdList.size() > 0) {
                dto.setUserIdList(userIdList);
            } else {
                userIdList = new HashSet<>();
                userIdList.add(0L);
                dto.setUserIdList(userIdList);
            }
        }
        Page infoPageList = baseMapper.getPlanPage(page, dto);
        infoPageList.setRecords(this.viewConversion(infoPageList.getRecords()));
        return infoPageList;
    }

    @Override
    public Page<PlanVo> getPlanTimeIntervalPage(Page page, PlanDto dto) {
        Plan plan = JSONObject.parseObject(JSON.toJSONString(dto), Plan.class);
        QueryWrapper<Plan> queryWrapper = new QueryWrapper<>();
        Date startDate = dto.getPlanBegindate();
        Date endDate = dto.getPlanEnddate();
        String inspectUsers = dto.getInspectUsers();
        String planState = dto.getPlanState();
        String inspectType = dto.getInspectType();
        if (StringUtils.isEmpty(dto.getFlag())) {
            // 当前部门下用户才有权限
            Long departmentId = SecurityUtils.getUser().getDepartmentId();
            Set<Long> userIdList = departmentClient.getDeptUserList(String.valueOf(departmentId)).getResult().stream().map(User::getId).collect(Collectors.toSet());
            queryWrapper.in("CREATE_USER", userIdList);
        }
        if (null != startDate) {
            queryWrapper.le("PLAN_BEGINDATE", startDate);
            plan.setPlanBegindate(null);

        }
        if (null != endDate) {
            queryWrapper.ge("PLAN_ENDDATE", endDate);
            plan.setPlanEnddate(null);
        }
        if (!StringUtils.isEmpty(inspectType)) {
            List<String> longList = Arrays.stream(inspectType.split(Constant.CSV)).collect(Collectors.toList());
            longList.forEach(info -> {
                queryWrapper.like("INSPECT_TYPE", info);
            });

            plan.setInspectType(null);
        }
        if (!StringUtils.isEmpty(planState)) {
            List<String> longList = Arrays.stream(planState.split(Constant.CSV)).collect(Collectors.toList());
            queryWrapper.in("PLAN_STATE", longList);
            plan.setPlanState(null);
        }

        if (!StringUtils.isEmpty(inspectUsers)) {
            List<Long> longList = Arrays.stream(inspectUsers.split(Constant.CSV)).map(s -> Long.parseLong(s.trim()))
                    .collect(Collectors.toList());
            List<PlanInspectUser> list = planInspectUserService.list(new QueryWrapper<PlanInspectUser>().lambda().in(PlanInspectUser::getUserId, longList));
            if (null != list && list.size() > 0) {
                Set<Long> collect = list.stream().map(PlanInspectUser::getPlanId).collect(Collectors.toSet());
                queryWrapper.in("ID", collect);
            } else {
                queryWrapper.in("ID", 0);
            }
        } else {
            if (StringUtils.isEmpty(dto.getMouthId())) {
                queryWrapper.in("ID", 0);
            }

        }
        queryWrapper.setEntity(plan);
        queryWrapper.orderByDesc("CREATE_TIME");
        Page infoPageList = this.page(page, queryWrapper);
        infoPageList.setRecords(this.viewConversion(infoPageList.getRecords()));
        return infoPageList;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Plan> savaPlanInfo(PlanDto parDto) throws BusinessException {
        // 获取巡检周期类型
        Period period = periodService.getById(parDto.getPeriodId());
        Optional.ofNullable(period).orElseThrow(() -> new BusinessException(Constant.PLAN_PERIOD_NULL_CODE, Constant.PLAN_PERIOD_NULL));
        log.info("新增计划参数{}",JSON.toJSONString(parDto));
        Plan plan = JSON.parseObject(JSON.toJSONString(parDto), Plan.class);
        if (IsDispatchingEnum.IS_DISPATCHING_YES.getCode().equals(parDto.getIsDispatching())) {
            plan.setPlanState(PlanStateEnum.PLAN_STATE_UNENFORCEABLE.getCode());
        }
        // 判断传入类型是否为自定义,若为自定义则赋值天数
        Integer intervalTime = period.getIntervalDay();
        if (null == intervalTime) {
            intervalTime = parDto.getIntervalDay();
        }
        // 计算巡检任务的集合
        List<Plan> planList = this.calculatePlanList(plan, intervalTime);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (Plan one : planList) {
            Date begin = DateUtil.formatDate(format.format(one.getPlanBegindate()), "yyyy-MM-dd HH:mm:ss");
            Date end = DateUtil.formatDate(format.format(one.getPlanEnddate()), "yyyy-MM-dd HH:mm:ss");
            one.setPlanBegindate(begin);
            one.setPlanEnddate(end);
            this.save(one);
        }
        log.info("新增计划{}",JSON.toJSONString(planList));
        // 新增到 计划与巡察组关联表,计划与巡查人关联表 ; 这个分开
        Long inspectGroupId = parDto.getInspectGroupId();
        String inspectUsers = parDto.getInspectUsers();
        List<String> asList = Arrays.asList(inspectUsers.split(Constant.CSV));
        planList.forEach(info -> {
            Long planId = info.getId();
            PlanInspectGroup inspectGroup = new PlanInspectGroup();
            inspectGroup.setPlanId(planId);
            inspectGroup.setInspectGroupId(inspectGroupId);
            planInspectGroupService.save(inspectGroup);
            asList.forEach(userid -> {
                PlanInspectUser inspectUser = new PlanInspectUser();
                inspectUser.setPlanId(planId);
                inspectUser.setUserId(Long.valueOf(userid));
                planInspectUserService.save(inspectUser);
            });
        });
        log.info("新增巡检组{},巡检人{}",inspectGroupId,inspectUsers);
        // 新增对应计划类型完成率初始化
        List<Plantype> planTypeOverList = parDto.getPlanTypeOverList();
        if (null != planTypeOverList && planTypeOverList.size() > 0) {
            // 存入对应厂站计划信息
            List<PlanFactory> factoryList = parDto.getFactoryList();
            if (null != factoryList && factoryList.size() > 0) {
                planList.forEach(info -> factoryList.forEach(factory -> {
                    factory.setPlanId(info.getId());
                    planFactoryService.save(factory);
                    factory.setId(null);
                }));

                log.info("新增设备列表{}",JSON.toJSONString(factoryList));
                this.savePlanTypeDevice(planList, planTypeOverList, factoryList);
                plan.setNormal("0");
                this.update(new UpdateWrapper<Plan>().lambda().in(Plan::getId,planList.stream().map(Plan::getId).collect(Collectors.toSet()))
                        .set(Plan::getNormal,"0"));
            }
            // 存入对应的点到位信息
            List<Pointtemp> pointTempList = parDto.getPointTempList();

            if (null != pointTempList && pointTempList.size() > 0) {
                planList.forEach(info -> pointTempList.forEach(p -> {
                    p.setPlanId(info.getId());
                    pointtempService.save(p);
                    p.setId(null);
                }));

                log.info("新增点到位列表{}",JSON.toJSONString(pointTempList));
                this.savePlanTypePointTemp(planList, planTypeOverList, pointTempList);
                plan.setNormal("1");
                this.update(new UpdateWrapper<Plan>().lambda().in(Plan::getId,planList.stream().map(Plan::getId).collect(Collectors.toSet()))
                        .set(Plan::getNormal,"1"));
            }
        }
        // 处理普通任务派发任务
        if (IsDispatchingEnum.IS_DISPATCHING_YES.getCode().equals(parDto.getIsDispatching())) {
            // 判断计划类型是否为 计划/维护
            Long planType = parDto.getPlanType();
            log.info("派发任务类型{}",planType);
            if ("1".equals(parDto.getIsTrouble())) {
                iPlanMessageService.planSendMessageTrouble(planList);
            }
            if (0L == planType) {
                iPlanMessageService.planSendMessage(planList);
            } else {
                iPlanMessageService.planSendMessageMaintain(planList);
            }
        }
        return planList;
    }

    @Override
    public PlanVo getPlanInfo(Long id) throws BusinessException {
        // 基本参数赋值
        PlanVo planVo = JSON.parseObject(JSON.toJSONString(this.getById(id)), PlanVo.class);
        // 巡检组/巡检人赋值
        List<PlanInspectGroup> groups = planInspectGroupService.list(new QueryWrapper<PlanInspectGroup>().lambda().eq(PlanInspectGroup::getPlanId, id));
        if (null != groups && groups.size() > 0) {
            PlanInspectGroup inspectGroup = groups.get(0);
            Long inspectGroupId = inspectGroup.getInspectGroupId();
            if (null != inspectGroupId) {
                planVo.setInspectGroup(inspectGroupId.toString());
            }
        }

        List<PlanInspectUser> list = planInspectUserService.list(new QueryWrapper<PlanInspectUser>().lambda().eq(PlanInspectUser::getPlanId, id));
        StringBuffer str = new StringBuffer("");
        list.forEach(info -> {
            str.append(info.getUserId()).append(Constant.CSV);

        });
        if (!StringUtils.isEmpty(str)) {
            planVo.setInspectUserList(str.deleteCharAt(str.length() - 1).toString());
        }
        planVo.setPlanFactoryList(planFactoryService.list(new QueryWrapper<PlanFactory>().lambda().eq(PlanFactory::getPlanId, id)));

        return planVo;
    }

    @Override
    public List<PlanDetailVo> getPlanDetail(Long id, String flag) {
        List<PlanDetailVo> voList = new ArrayList<>();
        // 获取计划信息
        Plan plan = this.getById(id);
        // 获取子计划信息
        List<PlanchildVo> planChildVo = this.getPlanChildVo(id, flag);
        if (null != planChildVo && planChildVo.size() > 0) {
            planChildVo.forEach(info -> {
                PlanDetailVo vo = new PlanDetailVo();
                Long childId = info.getId();
                // 子计划添加
                vo.setPlanChildVo(info);
                // 巡查记录
                List<RecordVo> planRecordVo = this.getPlanRecordVo(info.getId());
                vo.setRecordVoList(planRecordVo);
                // 管线记录
                List<Piperecord> pipeRecordList = piperecordService.list(new QueryWrapper<Piperecord>().lambda().eq(Piperecord::getPlanChildid, childId));
                if (null != pipeRecordList && pipeRecordList.size() > 0) {
                    vo.setPipeRecordVoList(piperecordService.viewConversion(pipeRecordList));
                }
                // 水压记录
                List<Pressrecord> pressRecordList = pressrecordService.list(new QueryWrapper<Pressrecord>().lambda().eq(Pressrecord::getPlanChildid, childId));
                if (null != pressRecordList && pressRecordList.size() > 0) {
                    vo.setPressRecordVoList(pressrecordService.viewConversion(pressRecordList));
                }
                // 消防栓记录
                List<Hydrantrecord> hydrantRecordList = hydrantrecordService.list(new QueryWrapper<Hydrantrecord>().lambda().eq(Hydrantrecord::getPlanChildid, childId));
                if (null != hydrantRecordList && hydrantRecordList.size() > 0) {
                    vo.setHydrantRecordList(hydrantRecordList);
                }
                // 探漏记录
                List<LeakRecord> leakRecordList = leakRecordService.list(new QueryWrapper<LeakRecord>().lambda().eq(LeakRecord::getPlanChildId, childId));
                if (null != leakRecordList && leakRecordList.size() > 0) {
                    vo.setLeakRecordList(leakRecordList);
                }
                // 计划信息
                List<Plan> list = new ArrayList<>();
                list.add(plan);
                vo.setPlanVo(this.viewConversion(list).get(0));
                voList.add(vo);
            });

        }


        return voList;
    }

    private List<PlanchildVo> getPlanChildVo(Long id, String flag) {
        Set<Long> userIdList = new HashSet<>();
        if (IsOverEnum.IS_OVER_NO.getCode().equals(flag)) {
            // 当前部门下的用户子计划
            // 当前部门下用户才有权限
            Long departmentId = SecurityUtils.getUser().getDepartmentId();
            Set<Long> collect = departmentClient.getDeptUserList(String.valueOf(departmentId)).getResult().stream().map(User::getId).collect(Collectors.toSet());
            userIdList.addAll(collect);
        } else {
            userIdList.add(SecurityUtils.getUserId());
        }
        List<Planchild> list = planchildService.list(new QueryWrapper<Planchild>().lambda()
                .eq(Planchild::getPlanId, id)
                .in(Planchild::getRespUser, userIdList));
        if (list.size() > 0) {
            return planchildService.viewConversion(list);
        }
        return null;
    }

    /**
     * 过程上报记录
     *
     * @param planChildId
     * @return
     */
    private List<RecordVo> getPlanRecordVo(Long planChildId) {
        List<Record> list = recordService.list(new QueryWrapper<Record>().lambda().eq(Record::getPlanChildid, planChildId));
        if (null != list && list.size() > 0) {
            List<RecordVo> recordVoList = recordService.viewConversion(list);
            recordVoList.sort(Comparator.comparing(RecordVo::getCreateTime).reversed());
            return recordVoList;
        }
        return null;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePlanInfo(PlanDto parDto) throws BusinessException {
        if (!iDisposeDateService.isDisposePermissions(parDto.getCreateUser())) {
            throw new BusinessException(Constant.IS_DISPOSE_PERMISSIONS_NULL_CODE, Constant.IS_DISPOSE_PERMISSIONS_NULL);
        }
        // 对已下发未开始的临时任务，可对其巡检任务内容进行修改。计划性任务不可修改。
        Plan byId = this.getById(parDto.getId());
        String planState = byId.getPlanState();
        if (PlanStateEnum.PLAN_STATE_NOT_SUBMITTED.getCode().equals(planState) || PlanStateEnum.PLAN_STATE_NOT_AUDIT.getCode().equals(planState)) {
            // 清空信息
            Long id = parDto.getId();
            List<Long> idList = new ArrayList<>();
            idList.add(id);

            this.deletePlan(idList);
            this.removeById(id);
            // 走保存
            // 清空id
            parDto.setId(null);
            this.savaPlanInfo(parDto);
        } else {
            throw new BusinessException(Constant.TASK_PLAN_NOT_UPDATE_CODE, Constant.TASK_PLAN_NOT_UPDATE);
        }


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePlanInfo(List<Long> idList) throws BusinessException {
        // 对已下发未开始的临时任务，可对其巡检任务内容进行删除。计划性任务不可删除。
        List<Plan> list = this.list(new QueryWrapper<Plan>().lambda().in(Plan::getId, idList));
        list.forEach(info -> {
            if (!iDisposeDateService.isDisposePermissions(info.getCreateUser())) {
                throw new BusinessException(Constant.IS_DISPOSE_PERMISSIONS_NULL_CODE, Constant.IS_DISPOSE_PERMISSIONS_NULL);
            }
            Plan byId = this.getById(info.getId());
            String planState = byId.getPlanState();
//            String planType = info.getPlanType();
//            if (PlanTypeEnum.PLAN_TYPE_MONTH.getCode().equals(planType)) {
//                throw new BusinessException(Constant.TASK_PLAN_MONTH_NOT_DELETE_CODE, Constant.TASK_PLAN_MONTH_NOT_DELETE);
//            }
            if (PlanStateEnum.PLAN_STATE_NOT_SUBMITTED.getCode().equals(planState) || PlanStateEnum.PLAN_STATE_NOT_AUDIT.getCode().equals(planState)) {
                this.deletePlan(idList);
            } else {
                throw new BusinessException(Constant.TASK_PLAN_NOT_DELETE_CODE, Constant.TASK_PLAN_NOT_DELETE);
            }

        });
        this.removeByIds(idList);

    }

    private void deletePlan(List<Long> planIdList) {
        planFactoryService.remove(new QueryWrapper<PlanFactory>().lambda().in(PlanFactory::getPlanId,planIdList));
        plantypeService.remove(new QueryWrapper<Plantype>().lambda().in(Plantype::getPlanId,planIdList));
        planchildService.remove(new QueryWrapper<Planchild>().lambda().in(Planchild::getPlanId,planIdList));
        // 删除点到位信息
        pointtempService.remove(new QueryWrapper<Pointtemp>().lambda().in(Pointtemp::getPlanId, planIdList));
        // 删除用户关联计划的信息
        // 清楚中间表关联数据 计划与巡察组关联表,计划与巡查人关联表
        planInspectGroupService.remove(new QueryWrapper<PlanInspectGroup>().lambda().in(PlanInspectGroup::getPlanId, planIdList));
        planInspectUserService.remove(new QueryWrapper<PlanInspectUser>().lambda().in(PlanInspectUser::getPlanId, planIdList));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePlanState(Long planId, String planState, Long userId) {

        Plan plan = this.getById(planId);
        // 若修改当前计划状态 为 3 正在执行
        if (PlanStateEnum.PLAN_STATE_BEING_PERFORMED.getCode().equals(planState)) {
            // 巡检计划为 2 未开始 或 5 已开始未执行
            if (PlanStateEnum.PLAN_STATE_NOT_START.getCode().equals(plan.getPlanState()) || PlanStateEnum.PLAN_STATE_EXECUTION_NOT_STARTED.getCode().equals(plan.getPlanState())) {
                // 巡检计划巡检开始时间若大于当前时间则不允许启动
                LocalDateTime startTime = DateTimeUtil.fromLong2LocalDateTime(plan.getPlanBegindate().getTime());
                if (LocalDateTime.now().isBefore(startTime)) {
                    throw new BusinessException(Constant.TASK_IS_PLAN_STATE_BEING_TIME_CODE, Constant.TASK_IS_PLAN_STATE_BEING_TIME);
                }
                // 判断当前用户是否已经签到
                if (SignTypeEnum.SIGN_TYPE_YES.getCode().equals(pdasignService.getUserSignState(userId))) {
                    // 获取对应用户的计划列表
                    List<PlanInspectUser> planList = planInspectUserService.list(new QueryWrapper<PlanInspectUser>().lambda().eq(PlanInspectUser::getUserId, userId));
                    List<PlanInspectUser> filterList = planList.stream().filter(p -> PlanStateEnum.PLAN_STATE_BEING_PERFORMED.getCode().equals(this.getById(p.getPlanId()).getPlanState())).collect(Collectors.toList());
                    // 判断当前用户是否存在正在执行的计划
                    if (filterList.size() > 0) {
                        throw new BusinessException(Constant.TASK_IS_PLAN_STATE_BEING_PERFORMED_CODE, Constant.TASK_IS_PLAN_STATE_BEING_PERFORMED);
                    }
                    plan.setPlanState(planState);
                    this.updateById(plan);

                } else {
                    throw new BusinessException(Constant.TASK_IS_PLAN_STATE_BEING_PERFORMED_SIGN_CODE, Constant.TASK_IS_PLAN_STATE_BEING_PERFORMED_SIGN);

                }
            } else {
                throw new BusinessException(Constant.TASK_IS_PLAN_STATE_OVER_PERFORMED_CODE, Constant.TASK_IS_PLAN_STATE_OVER_PERFORMED + PlanStateEnum.getCodeForValue(plan.getPlanState()) + "不可启动");

            }


        } else if (PlanStateEnum.PLAN_STATE_EXECUTION_NOT_STARTED.getCode().equals(planState)) {
            plan.setPlanState(planState);
            this.updateById(plan);
        }
    }


    @Override
    public Plan stopPlan(Plan plan, Planstop planStop) {
        // 暂停任务1.获取暂停申请计划重启时间2.修改当前主计划状态为未开始,计划巡检时间
        Date applyStartTime = planStop.getApplyStarttime();
        Date applyEndTime = planStop.getApplyEndtime();
        plan.setPlanBegindate(applyStartTime);
        plan.setPlanEnddate(applyEndTime);
        plan.setPlanState(PlanStateEnum.PLAN_STATE_PROJECT_SUSPENDED.getCode());
        return plan;
    }

    @Override
    public Plan disusePlan(Plan plan, Plancancle plancancle) {
        // 作废任务1.修改当前主计划状态为计划已作废
        plan.setPlanState(PlanStateEnum.PLAN_STATE_PLAN_DISUSE.getCode());
        return plan;
    }

    /**
     * 巡检任务次数计算
     *
     * @param plan        当前巡检计划内容
     * @param intervalTime 计划周期间隔时间
     * @return 巡检任务集合
     */
    private List<Plan> calculatePlanList(Plan plan, Integer intervalTime) {
        Long periodId = plan.getPeriodId();
        Date planBeginDate = plan.getPlanBegindate();
        Date planEndDate = plan.getPlanEnddate();
        List<Plan> planList = new ArrayList<>();
        Map<LocalDateTime, LocalDateTime> planDateMap = new LinkedHashMap<>(12);
        LocalDateTime startTime = DateTimeUtil.fromLong2LocalDateTime(planBeginDate.getTime());
        LocalDateTime endTime = DateTimeUtil.fromLong2LocalDateTime(planEndDate.getTime());
        if (1L == periodId) {
            // 一日一巡
            planDateMap.putAll(DateTimeUtil.getDayPeriodMap(startTime, endTime));
        } else if (2L == periodId) {
            // 一周一巡
            planDateMap.putAll(DateTimeUtil.getWeekPeriodMap(startTime, endTime));
        } else if (3L == periodId) {
            // 一月一巡
            planDateMap.putAll(DateTimeUtil.getMonthPeriodMap(startTime, endTime));
        } else if (4L == periodId) {
            // 自定义
//            planDateMap.put(startTime, endTime);
            planDateMap.putAll(DateTimeUtil.getCustomPeriodMap(startTime, endTime, intervalTime));
        } else if (5L == periodId) {
            planDateMap.putAll(DateTimeUtil.getCustomHourPeriodMap(startTime, endTime, intervalTime));
        }
        planDateMap.forEach((k, v) -> {
            Plan info = JSON.parseObject(JSON.toJSONString(plan), Plan.class);
            info.setPlanBegindate(DateTimeUtil.convertLDTToDate(k));
            info.setPlanEnddate(DateTimeUtil.convertLDTToDate(v));
            planList.add(info);
        });
        return planList;
    }


    private void savePlanTypeDevice(List<Plan> planListId, List<Plantype> planTypeOverList, List<PlanFactory> planFactoryList) {
        planListId.forEach(plan -> {
            // 获取计划id
            Long planId = plan.getId();
            // 按照类型分组
            Map<Long, List<PlanFactory>> collect = planFactoryList.stream().filter(info -> null != info.getInspectTypeId()).collect(Collectors.groupingBy(PlanFactory::getInspectTypeId));
            Map<Long, Float> floatMap = planTypeOverList.stream().collect(Collectors.toMap(Plantype::getTypeId, Plantype::getCompletionRate, (key1, key2) -> key2));
            collect.forEach((k, v) -> {
                Plantype plantype = new Plantype();
                plantype.setPlanId(planId);
                plantype.setTypeId(k);
                plantype.setCompletionRate(floatMap.get(k));
                plantype.setTotalCount(BigDecimal.valueOf(v.size()));
                plantype.setTotalLength(BigDecimal.ZERO);
                plantypeService.save(plantype);
            });
        });
    }

    private void savePlanTypePointTemp(List<Plan> planList, List<Plantype> planTypeOverList, List<Pointtemp> pointTempList) {
        planList.forEach(plan -> {
            // 获取计划id
            Long planId = plan.getId();
            // 按照类型分组
            Map<Long, List<Pointtemp>> collect = pointTempList.stream().filter(info -> null != info.getInspectTypeId()).collect(Collectors.groupingBy(Pointtemp::getInspectTypeId));
            Map<Long, Float> floatMap = planTypeOverList.stream().collect(Collectors.toMap(Plantype::getTypeId, Plantype::getCompletionRate, (key1, key2) -> key2));
            collect.forEach((k, v) -> {
                Plantype plantype = new Plantype();
                plantype.setPlanId(planId);
                plantype.setTypeId(k);
                plantype.setCompletionRate(floatMap.get(k));
                plantype.setTotalCount(BigDecimal.valueOf(v.size()));
                double sum = v.stream().filter(i -> null != i.getPipeLength()).mapToDouble(i -> i.getPipeLength().doubleValue()).sum();
                plantype.setTotalLength(BigDecimal.valueOf(sum));
                plantypeService.save(plantype);
            });
        });

    }
}

