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

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
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.api.UserClent;
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.maintain.RepairorderMapper;
import com.tofly.gpsboot.mapper.plan.PlanMapper;
import com.tofly.gpsboot.service.comm.IAuditService;
import com.tofly.gpsboot.service.comm.IDisposeDateService;
import com.tofly.gpsboot.service.config.InspectgroupService;
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.*;
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.Department;
import com.tofly.pojo.User;
import com.tofly.pojo.plan.*;
import com.tofly.pojo.plan.dto.PlanDto;
import com.tofly.pojo.plan.vo.*;
import com.tofly.pojo.plan.vo.TreeVo;
import groovy.transform.Synchronized;
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.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")
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 UserClent userClent;

    @Autowired
    private HydrantrecordService hydrantrecordService;

    @Autowired
    private IAuditService iAuditService;

    @Autowired
    private LeakRecordService leakRecordService;

    @Autowired
    private PlantypeService plantypeService;

    @Autowired
    private CheckhistoryService checkhistoryService;
    @Autowired
    private RepairorderMapper repairorderMapper;
    @Autowired
    private InspectgroupService inspectgroupService;
    @Autowired
    private GroupuserService groupuserService;

    @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);
            // 转换计划类型/巡查类型/是否查看/是否超时/巡检计划状态/巡检组/巡检人/是否自动派工/是否暂停/是否作废
            baseInfo.setPlanType(PlanTypeEnum.getCodeForValue(info.getPlanType()));
            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.setInspectType(inspecttypeService.getInspectTypeName(longList));
            }
            baseInfo.setIsread(IsReadEnum.getCodeForValue(info.getIsread()));
            baseInfo.setIsover(IsOverEnum.getCodeForValue(info.getIsover()));
            baseInfo.setPlanState(PlanStateEnum.getCodeForValue(info.getPlanState()));
            baseInfo.setInspectGroup(planInspectGroupService.getInspectGroupName(info.getId()));
            baseInfo.setInspectUserList(planInspectUserService.getInspectUserList(info.getId()));
            baseInfo.setIsDispatching(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.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);
            }
        }
        Page infoPageList = baseMapper.getPlanPage(page, dto);
        infoPageList.setRecords(this.viewConversion(infoPageList.getRecords()));
        return infoPageList;
    }


    @Override
    public Page<PlanVo> getPlanTimeIntervalPage(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);
            }
        }
        Page infoPageList = baseMapper.getPlanPage(page, dto);
        infoPageList.setRecords(this.viewConversion(infoPageList.getRecords()));
        return infoPageList;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @Synchronized
    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));

        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 intervalDay = period.getIntervalDay();
        if (null == intervalDay) {
            intervalDay = parDto.getIntervalDay();
        }
        // 计算巡检任务的集合
        List<Plan> planList = this.calculatePlanList(plan, intervalDay);
//        this.saveBatch(planList);
        planList.forEach(this::save);

        // 新增到 计划与巡察组关联表,计划与巡查人关联表 ; 这个分开
        Long inspectGroupId = parDto.getInspectGroupId();
        String inspectUsers = parDto.getInspectUsers();
        List<String> asList = Arrays.asList(inspectUsers.split(Constant.SEMICOLON));
        List<PlanInspectGroup> savePlanInspectGroup = new ArrayList<>();
        List<PlanInspectUser> savePlanInspectUser = new ArrayList<>();
        planList.forEach(info -> {
            Long planId = info.getId();
            PlanInspectGroup inspectGroup = new PlanInspectGroup();
            inspectGroup.setPlanId(planId);
            inspectGroup.setInspectGroupId(inspectGroupId);
            savePlanInspectGroup.add(inspectGroup);
            asList.forEach(userid -> {
                PlanInspectUser inspectUser = new PlanInspectUser();
                inspectUser.setPlanId(planId);
                inspectUser.setUserId(Long.valueOf(userid));
                savePlanInspectUser.add(inspectUser);
            });

        });
        planInspectGroupService.saveBatch(savePlanInspectGroup);
        planInspectUserService.saveBatch(savePlanInspectUser);
//        planInspectGroupService.saveBatch(planInspectGroupList);
//        planInspectUserService.saveBatch(planInspectUserList);
        // 存入对应的点到位信息
        List<Pointtemp> pointTempList = parDto.getPointTempList();
        if (null != pointTempList && pointTempList.size() > 0) {
            planList.forEach(info -> {
                pointTempList.forEach(temp -> {
                    temp.setPlanId(info.getId());
                    pointtempService.save(temp);
                });
            });
//            pointtempService.saveBatch(pointTempList);
            // 新增对应计划类型完成率初始化
            List<Plantype> planTypeOverList = parDto.getPlanTypeOverList();
            if (null != planTypeOverList && planTypeOverList.size() > 0) {
                this.savePlanType(planList, planTypeOverList, pointTempList);
            } else {
                throw new BusinessException(Constant.TASK_IS_REPAIR_ORDER_ADD_NULL_CODE, Constant.TASK_IS_REPAIR_ORDER_ADD_NULL);
            }
        } else {
            throw new BusinessException(Constant.TASK_IS_PLAN_STATE_POINT_PLACE_CODE, Constant.TASK_IS_PLAN_STATE_POINT_PLACE);
        }


        // 处理普通任务派发任务
        if (IsDispatchingEnum.IS_DISPATCHING_YES.getCode().equals(parDto.getIsDispatching())) {

            // 判断计划类型 隐患 工地 计划
            String planType = parDto.getPlanType();
            if (PlanTypeEnum.PLAN_TYPE_TROUBLE.getCode().equals(planType)) {
                iPlanMessageService.planSendMessageTrouble(planList);
            } else if (PlanTypeEnum.PLAN_TYPE_BUILD.getCode().equals(planType)) {
                iPlanMessageService.planSendMessageBuild(planList);
            } else {
                iPlanMessageService.planSendMessage(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.setPlanTypeOverList(plantypeService.list(new QueryWrapper<Plantype>().lambda().eq(Plantype::getPlanId, id)));

        return planVo;
    }

    @Override
    public List<PlanDetailVo> getPlanDetail(Long id, String flag, Long deptId) {
        List<PlanDetailVo> voList = new ArrayList<>();
        // 获取计划信息
        Plan plan = this.getById(id);
        // 获取子计划信息
        List<PlanchildVo> planChildVo = this.getPlanChildVo(id, flag, deptId);
        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;
    }

    @Override
    public Long getUserPlanNum(Date startDate, Date endDate, Long userId) {
        return baseMapper.getUserPlanNum(startDate, endDate, userId);
    }

    @Override
    public PlanYearReportVo getReportPlanYear() {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        return this.baseMapper.getReportPlanYear(year);
    }

    @Override
    public PlanYearReportVo getReportPlanMonth() {
        return this.baseMapper.getReportPlanMonth();
    }

    @Override
    public List<TreeVo> deptInspectTree(String isQueryGroup) {
        List<Department> departmentList = departmentClient.departmentListAll().getResult();
        List<User> userList = this.baseMapper.getUserAll();
        List<TreeVo> treeVoList = new ArrayList<>();
        departmentList.forEach(e -> {
            TreeVo treeVo = new TreeVo();
            treeVo.setId(e.getId());
            treeVo.setLabel(e.getName());
            treeVo.setType("1");
            if (isQueryGroup.equals("0")) {
                List<User> userListFinal = userList.stream().filter(u -> Objects.equals(u.getDepartmentId(), e.getId())).collect(Collectors.toList());
                if (CollUtil.isEmpty(userListFinal)) {
                    treeVo.setChildren(new ArrayList<>());
                    treeVoList.add(treeVo);
                    return;
                }
                List<TreeVo> treeVoList2 = new ArrayList<>();
                userListFinal.forEach(userl -> {
                    TreeVo treeVo2 = new TreeVo();
                    treeVo2.setId(userl.getId());
                    treeVo2.setLabel(userl.getRealName());
                    treeVo2.setType("3");
                    treeVo2.setChildren(new ArrayList<>());
                    treeVoList2.add(treeVo2);
                });
                treeVo.setChildren(CollUtil.isEmpty(treeVoList2) ? new ArrayList<>():treeVoList2);
                treeVoList.add(treeVo);
                return;
            }
            List<Inspectgroup> inspectgroupList = inspectgroupService.list(new QueryWrapper<Inspectgroup>()
                    .lambda().eq(Inspectgroup::getDeptId, e.getId()));
            List<TreeVo> treeVoList1 = new ArrayList<>();
            inspectgroupList.forEach(info -> {
                TreeVo treeVo1 = new TreeVo();
                treeVo1.setId(info.getId());
                treeVo1.setLabel(info.getName());
                treeVo1.setType("2");
                List<Groupuser> groupuserList = groupuserService.list(new QueryWrapper<Groupuser>()
                        .lambda().eq(Groupuser::getGroupId, info.getId()));
                List<TreeVo> treeVoList2 = new ArrayList<>();
                groupuserList.forEach(user -> {
                    TreeVo treeVo2 = new TreeVo();
                    treeVo2.setId(Long.parseLong(user.getUserId()));
                    List<User> userListFinal = userList.stream().filter(u -> Objects.equals(u.getId(), treeVo2.getId())).collect(Collectors.toList());
                    if (CollUtil.isEmpty(userListFinal)) {
                        return;
                    }
                    treeVo2.setLabel(userListFinal.get(0).getRealName());
                    treeVo2.setType("3");
                    treeVo2.setChildren(new ArrayList<>());
                    treeVoList2.add(treeVo2);
                });
                treeVo1.setChildren(CollUtil.isEmpty(treeVoList2) ? new ArrayList<>():treeVoList2);
                treeVoList1.add(treeVo1);
            });
            treeVo.setChildren(CollUtil.isEmpty(treeVoList1) ? new ArrayList<>():treeVoList1);
            treeVoList.add(treeVo);
        });
        return treeVoList;
    }

    private List<PlanchildVo> getPlanChildVo(Long id, String flag, Long deptId) {
        Set<Long> userIdList = new HashSet<>();
        if (IsOverEnum.IS_OVER_NO.getCode().equals(flag)) {
            Long departmentId = deptId == null ? SecurityUtils.getUser().getDepartmentId() : deptId;
            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);
        }
        // 对已下发未开始的临时任务，可对其巡检任务内容进行修改。计划性任务不可修改。
        String planState = parDto.getPlanState();
//        String planType = parDto.getPlanType();
//        if (PlanTypeEnum.PLAN_TYPE_MONTH.getCode().equals(planType)) {
//            throw new BusinessException(Constant.TASK_PLAN_MONTH_NOT_UPDATE_CODE, Constant.TASK_PLAN_MONTH_NOT_UPDATE);
//        }
        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);
            // 走保存
            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);

            }
            String planState = info.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) {
        // 删除点到位信息
        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));
        // 清空计划类型
        plantypeService.remove(new QueryWrapper<Plantype>().lambda().in(Plantype::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)) {
            // 巡检计划巡检开始时间若大于当前时间则不允许启动
            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))) {
                throw new BusinessException(Constant.TASK_IS_PLAN_STATE_BEING_PERFORMED_SIGN_CODE, Constant.TASK_IS_PLAN_STATE_BEING_PERFORMED_SIGN);
            }
            // 巡检主计划为 2 已开始、 5已开始未执行
            if (PlanStateEnum.PLAN_STATE_NOT_START.getCode().equals(plan.getPlanState())|| PlanStateEnum.PLAN_STATE_EXECUTION_NOT_STARTED.getCode().equals(plan.getPlanState())) {
                // 获取子计划中是否存在正在执行的任务
                long count = planchildService.list(new QueryWrapper<Planchild>().lambda().eq(Planchild::getRespUser,userId).eq(Planchild::getPlanState, IsPlanChildStateEnum.PLAN_STATE_BEING_PERFORMED.getCode())).stream().count();
                if (count > 0) {
                    throw new BusinessException(Constant.TASK_IS_PLAN_STATE_BEING_PERFORMED_CODE, Constant.TASK_IS_PLAN_STATE_BEING_PERFORMED);
                }else {
                    // 修改当前主计划下对应子计划状态为 3正在执行
                    planchildService.update(new UpdateWrapper<Planchild>().lambda()
                            .eq(Planchild::getPlanId,planId)
                            .eq(Planchild::getRespUser,userId)
                    .set(Planchild::getPlanState,IsPlanChildStateEnum.PLAN_STATE_BEING_PERFORMED.getCode()));
                }
            } 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)) {
            // 当前修改当前主计划对应子计划状态为 5 已开始未执行
            planchildService.update(new UpdateWrapper<Planchild>().lambda()
                    .eq(Planchild::getPlanId,planId)
                    .eq(Planchild::getRespUser,userId)
                    .set(Planchild::getPlanState,IsPlanChildStateEnum.PLAN_STATE_EXECUTION_NOT_STARTED.getCode()));
        }
    }


    @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 intervalDay 计划周期间隔时间
     * @return 巡检任务集合
     */
    private List<Plan> calculatePlanList(Plan plan, Integer intervalDay) {
        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 {
            // 自定义 只算一次
            planDateMap.put(startTime, endTime);
        }
        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 savePlanType(List<Plan> planList, List<Plantype> planTypeOverList, List<Pointtemp> pointTempList) {
        List<Plantype> savePlanType = new ArrayList<>();
        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));
                savePlanType.add(plantype);
            });
        });
        plantypeService.saveBatch(savePlanType);

    }

}
