package com.ruoyi.drill.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.AppUserTypeEnum;
import com.ruoyi.common.constant.DeletedEnum;
import com.ruoyi.common.constant.DrillEnum;
import com.ruoyi.common.constant.SysNoticeTitleRouteEnum;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.JWTUtil;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.drill.domain.DrillAnnualEmergency;
import com.ruoyi.drill.domain.DrillPerson;
import com.ruoyi.drill.domain.DrillPic;
import com.ruoyi.drill.domain.DrillPlan;
import com.ruoyi.drill.domain.DrillProcess;
import com.ruoyi.drill.domain.DrillRectificationProblems;
import com.ruoyi.drill.dto.DrillPlanDto;
import com.ruoyi.drill.dto.DrillPlanListDto;
import com.ruoyi.drill.dto.DrillPlanResultDto;
import com.ruoyi.drill.dto.DrillProcessDto;
import com.ruoyi.drill.dto.DrillRectificationProblemsDto;
import com.ruoyi.drill.mapper.DrillPlanMapper;
import com.ruoyi.drill.service.IDrillAnnualEmergencyService;
import com.ruoyi.drill.service.IDrillPersonService;
import com.ruoyi.drill.service.IDrillPicService;
import com.ruoyi.drill.service.IDrillPlanService;
import com.ruoyi.drill.service.IDrillProcessService;
import com.ruoyi.drill.service.IDrillRectificationProblemsService;
import com.ruoyi.system.domain.AppLogin;
import com.ruoyi.system.service.IAppLoginService;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysNoticeService;
import com.ruoyi.system.service.ISysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class DrillPlanServiceImpl extends ServiceImpl<DrillPlanMapper, DrillPlan> implements IDrillPlanService {

    @Resource
    private IDrillPersonService drillPersonService;
    @Resource
    private IDrillProcessService drillProcessService;
    @Resource
    private IDrillPicService drillPicService;
    @Resource
    private IDrillAnnualEmergencyService drillAnnualEmergencyService;
    @Resource
    private IDrillRectificationProblemsService drillRectificationProblemsService;
    @Resource
    private RedisCache redisCache;
    @Resource
    private ISysUserService userService;
    @Resource
    private ISysDeptService deptService;
    @Resource
    private ISysNoticeService sysNoticeService;
    @Resource
    private IAppLoginService appLoginService;

    public static final Map<String, String> MONTH_MAP = new LinkedHashMap<>();

    static {
        MONTH_MAP.put("january", "1");
        MONTH_MAP.put("february", "2");
        MONTH_MAP.put("march", "3");
        MONTH_MAP.put("april", "4");
        MONTH_MAP.put("may", "5");
        MONTH_MAP.put("june", "6");
        MONTH_MAP.put("july", "7");
        MONTH_MAP.put("august", "8");
        MONTH_MAP.put("september", "9");
        MONTH_MAP.put("october", "10");
        MONTH_MAP.put("november", "11");
        MONTH_MAP.put("december", "12");
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public AjaxResult saveAndUpdateDrillPlan(DrillPlanDto drillPlan) {
        if (Objects.isNull(getSysUserById(drillPlan.getDrillOrganizer()))) {
            return AjaxResult.warn("演习组织人不存在!");
        }
        if (Objects.isNull(getSysDeptById(drillPlan.getDrillDepartment()))) {
            return AjaxResult.warn("演习部门不存在!");
        }
        if (StringUtils.isEmpty(drillPlan.getDrillType())) {
            return AjaxResult.warn("请选择演习类型!");
        }

        String id = drillPlan.getId();
        // 1.判断是新增还是修改
        DrillPlan dp = new DrillPlan();
        BeanUtils.copyProperties(drillPlan, dp);
        Calendar instance = Calendar.getInstance();
        instance.setTime(dp.getPlanStartTime());
        long year = instance.get(Calendar.YEAR);
        long month = instance.get(Calendar.MONTH) + 1;
        String drillType = dp.getDrillType();

        List<DrillAnnualEmergency> list = drillAnnualEmergencyService.list(Wrappers.<DrillAnnualEmergency>lambdaQuery()
                .eq(DrillAnnualEmergency::getPlanYear, year)
                .eq(DrillAnnualEmergency::getPlanName, drillType));
        if (CollectionUtils.isEmpty(list)) {
            return AjaxResult.warn("根据预案[" + drillType + "]无需演习");
        } else {
            Optional<DrillAnnualEmergency> first = list.stream().filter(li -> Objects.equals(month, li.getPlanMonth())).findFirst();
            if (first.isPresent()) {
                dp.setDrillType(first.get().getId());
            } else {
                List<Long> collect = list.stream().map(DrillAnnualEmergency::getPlanMonth).collect(Collectors.toList());
                String join = StringUtils.join(collect, ",");
                return AjaxResult.warn("根据预案[" + drillType + "]演习仅需在[" + join + "]月演习");
            }
        }

        DrillPlan plan = this.getById(id);
        if (Objects.isNull(plan)) {
            if (this.count(Wrappers.<DrillPlan>lambdaQuery().eq(DrillPlan::getDrillType, dp.getDrillType())) > 0) {
                return AjaxResult.warn("[" + drillType + "]已经演习");
            }
            id = IdUtils.fastSimpleUUID();
            dp.setId(id);
            dp.setDrillSn(getDrillSn());
            dp.setCreateDefault();
        } else {
            if (Objects.equals(plan.getDrillStatus(), DrillEnum.DRILL_STATUS_YES.getValue())) {
                return AjaxResult.warn("已完成演习不允许修改");
            }
            dp.setId(id);
            dp.setIsDel(DeletedEnum.VALID.getValue());
            dp.setUpdateDefault();
        }
        // 2.校验数据
        List<DrillPerson> drillPersonList = drillPlan.getDrillPersonList();
        List<DrillProcess> drillProcessList = drillPlan.getDrillProcessList();
        List<String> drillDepartments = drillPlan.getDrillDepartmentsList();
        dp.setDrillDepartments(String.join(",", drillDepartments));
        if (CollectionUtils.isEmpty(drillPersonList)) {
            return AjaxResult.warn("演习人员不能为空");
        } else {
            for (DrillPerson drillPerson : drillPersonList) {
                Long person = drillPerson.getDrillPerson();
                if (Objects.isNull(person)) {
                    return AjaxResult.warn("演习人员不能为空!");
                }
                // 判断人是否存在于系统
                if (Objects.isNull(getSysUserById(person))) {
                    return AjaxResult.warn("演习人员不存在!");
                }
                drillPerson.setPlanId(id);
                drillPerson.setCreateDefault();
            }
        }
        if (CollectionUtils.isEmpty(drillProcessList)) {
            return AjaxResult.warn("演习确认项不能为空");
        } else {
            for (int i = 0; i < drillProcessList.size(); i++) {
                DrillProcess drillProcess = drillProcessList.get(i);
                if (StringUtils.isEmpty(drillProcess.getContentInfo())) {
                    return AjaxResult.warn("演习确认项不能为空!");
                }
                drillProcess.setPlanId(id);
                drillProcess.setConfirmStatus(DrillEnum.CONFIRM_STATUS_WAIT.getValue());
                drillProcess.setSortdNum(i + 1L);
                drillProcess.setCreateDefault();
            }
        }

        dp.setDrillStatus(DrillEnum.DRILL_STATUS_NO.getValue());
        dp.setProcessStatus(DrillEnum.PROCESS_STATUS_WAIT.getValue());
        dp.setPlanYear(year);
        dp.setPlanMonth(month);

        // 3.保存演习计划
        this.saveOrUpdate(dp);
        // 4.删除并新增演习过程确认项
        drillProcessService.remove(Wrappers.<DrillProcess>lambdaQuery().eq(DrillProcess::getPlanId, id));
        drillProcessService.saveBatch(drillProcessList);
        // 5.删除并新增演习人员
        drillPersonService.remove(Wrappers.<DrillPerson>lambdaQuery().eq(DrillPerson::getPlanId, id));
        drillPersonService.saveBatch(drillPersonList);
        return AjaxResult.success();
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public AjaxResult startPlanForApp(DrillPlanDto drillPlan) {
        // 校验参数
        if (StringUtils.isEmpty(JWTUtil.getPCUserId())) {
            return AjaxResult.error("获取用户异常");
        }
        // 获取app账号对应的pc的userId
        Long userId = Long.parseLong(JWTUtil.getPCUserId());
        String id = drillPlan.getId();
        DrillPlan plan = this.getById(id);
        if (Objects.isNull(plan) || !Objects.equals(plan.getDrillOrganizer(), userId)
                || Objects.equals(plan.getIsDel(), DeletedEnum.INVALID.getValue())) {
            return AjaxResult.warn("您无权完成此演习");
        }
        if (Objects.equals(plan.getDrillStatus(), DrillEnum.DRILL_STATUS_YES.getValue())) {
            return AjaxResult.warn("演习已完成");
        }
        List<DrillProcess> drillProcessList = drillPlan.getDrillProcessList();
        List<DrillPic> drillPicList = drillPlan.getDrillPicList();
        if (CollectionUtils.isEmpty(drillProcessList)) {
            return AjaxResult.warn("演习确认项不能为空");
        } else {
            for (DrillProcess drillProcess : drillProcessList) {
                if (StringUtils.isEmpty(drillProcess.getId())) {
                    return AjaxResult.warn("演习确认项不能为空!");
                }
                drillProcess.setConfirmStatus(DrillEnum.CONFIRM_STATUS_YES.getValue());
                drillProcess.setConfirmBy(userId);
                drillProcess.setConfirmTime(new Date());
                drillProcess.setUpdateDefaultForApp();
            }
        }
        if (CollectionUtils.isEmpty(drillPicList)) {
            return AjaxResult.warn("演习图片不能为空");
        } else {
            for (DrillPic drillPic : drillPicList) {
                if (StringUtils.isEmpty(drillPic.getPicUrl())) {
                    return AjaxResult.warn("演习图片不能为空!");
                }
                drillPic.setPlanId(id);
                drillPic.setCreateDefaultForApp();
            }
        }
        // 修改演习计划状态
        DrillPlan dp = new DrillPlan();
        dp.setId(id);
        dp.setDrillStatus(DrillEnum.DRILL_STATUS_YES.getValue());
        dp.setRealityStartTime(new Date());
        dp.setUpdateDefaultForApp();
        this.updateById(dp);
        // 修改确认项状态
        drillProcessService.updateBatchById(drillProcessList);
        // 添加图片
        drillPicService.saveBatch(drillPicList);
        // 修改年度演习计划状态
        String drillType = plan.getDrillType();
        DrillAnnualEmergency drillAnnualEmergency = new DrillAnnualEmergency();
        drillAnnualEmergency.setFinishBy(String.valueOf(userId));
        drillAnnualEmergency.setFinishTime(new Date());
        drillAnnualEmergency.setId(drillType);
        drillAnnualEmergency.setUpdateDefaultForApp();
        drillAnnualEmergencyService.updateById(drillAnnualEmergency);
        return AjaxResult.success();
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public AjaxResult summaryPlan(DrillPlanResultDto drillPlan) {
        String id = drillPlan.getId();
        DrillPlan plan = this.getById(id);
        if (Objects.isNull(plan) || Objects.equals(plan.getIsDel(), DeletedEnum.INVALID.getValue())) {
            return AjaxResult.warn("您无权查看");
        }
        List<DrillRectificationProblemsDto> drillRectificationProblemsDtos = drillPlan.getDrillRectificationProblemsList();
        List<DrillRectificationProblems> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(drillRectificationProblemsDtos)) {
            for (int i = 0; i < drillRectificationProblemsDtos.size(); i++) {
                DrillRectificationProblems drp = new DrillRectificationProblems();
                BeanUtils.copyProperties(drillRectificationProblemsDtos.get(i), drp);
                if (drillRectificationProblemsDtos.size() == 1
                        && StringUtils.isEmpty(drp.getProblemsInfo())
                        && StringUtils.isEmpty(drp.getRectificationInfo())
                        && Objects.isNull(drp.getPersonLiable())
                        && StringUtils.isEmpty(drp.getRectificationTerm())
                        && StringUtils.isEmpty(drp.getRectificationTerm())
                        && Objects.isNull(drp.getRectificationBy())
                        && Objects.isNull(drp.getRectificationTime())) {
                    continue;
                }

                if (StringUtils.isEmpty(drp.getProblemsInfo())) {
                    return AjaxResult.warn("问题描述不能为空!");
                }
                if (StringUtils.isEmpty(drp.getRectificationInfo())) {
                    return AjaxResult.warn("整改措施不能为空!");
                }
                if (Objects.isNull(drp.getPersonLiable())) {
                    return AjaxResult.warn("责任人不能为空!");
                }
                if (StringUtils.isEmpty(drp.getRectificationTerm())) {
                    return AjaxResult.warn("整改期限不能为空!");
                }
                if (StringUtils.isEmpty(drp.getRectificationTerm())) {
                    return AjaxResult.warn("整改期限不能为空!");
                }
                if (Objects.isNull(drp.getRectificationBy())) {
                    return AjaxResult.warn("整改人不能为空!");
                }
                if (Objects.isNull(drp.getRectificationTime())) {
                    return AjaxResult.warn("整改时间不能为空!");
                }
                drp.setPlanId(id);
                drp.setSortdNum(i + 1L);
                drp.setCreateDefault();
                list.add(drp);
            }
        }
        DrillPlan dp = new DrillPlan();
        dp.setId(id);
        dp.setDrillSummary(drillPlan.getDrillSummary());
        dp.setProcessStatus(DrillEnum.PROCESS_STATUS_WAIT.getValue());
        dp.setUpdateDefault();
        this.updateById(dp);
        drillRectificationProblemsService.remove(Wrappers.<DrillRectificationProblems>lambdaQuery().eq(DrillRectificationProblems::getPlanId, id));
        if (CollectionUtils.isNotEmpty(list)) {
            drillRectificationProblemsService.saveBatch(list);
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult statistics(String year) {
        List<DrillAnnualEmergency> drillAnnualEmergencyList = drillAnnualEmergencyService.list(Wrappers.<DrillAnnualEmergency>lambdaQuery()
                .eq(DrillAnnualEmergency::getPlanYear, year).orderByAsc(DrillAnnualEmergency::getSortdNum));
        List<DrillPlan> drillPlans = this.list(Wrappers.<DrillPlan>lambdaQuery().eq(DrillPlan::getPlanYear, year)
                .eq(DrillPlan::getDrillStatus, DrillEnum.DRILL_STATUS_YES.getValue())
                .eq(DrillPlan::getIsDel, DeletedEnum.VALID.getValue()));

        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, List<DrillAnnualEmergency>> collect = drillAnnualEmergencyList.stream().collect(Collectors.groupingBy(DrillAnnualEmergency::getPlanName));

        for (String planName : collect.keySet()) {
            Map<String, Object> map = new HashMap<>();
            List<Map<String, String>> lis = new ArrayList<>();
            long sort = 0;
            for (String s : MONTH_MAP.keySet()) {
                String type = "0";
                String month = MONTH_MAP.get(s);
                List<DrillAnnualEmergency> drillAnnualEmergencies = collect.get(planName);

                Optional<DrillAnnualEmergency> emergencyOptional = drillAnnualEmergencies.stream().filter(li ->
                        Objects.equals(year, String.valueOf(li.getPlanYear()))
                                && Objects.equals(month, String.valueOf(li.getPlanMonth()))).findFirst();
                if (emergencyOptional.isPresent()) {
                    DrillAnnualEmergency drillAnnualEmergency = emergencyOptional.get();
                    sort = drillAnnualEmergency.getSortdNum();
                    Optional<DrillPlan> first = drillPlans.stream().filter(li -> li.getDrillType().equals(drillAnnualEmergency.getId())).findFirst();
                    type = first.isPresent() ? "1" : "2";
                }

                Map<String, String> data = new HashMap<>();
                data.put("month", month + "月");
                data.put("type", type);
                lis.add(data);
            }
            map.put("planName", planName);
            map.put("data", lis);
            map.put("sort", sort);
            list.add(map);
        }

        list = list.stream().sorted(
                Comparator.comparing(o -> Long.valueOf(String.valueOf(o.get("sort"))))
        ).collect(Collectors.toList());

        return AjaxResult.success(list);
    }

    @Override
    public AjaxResult checkPlan() {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DATE);
        List<DrillAnnualEmergency> list = drillAnnualEmergencyService.list(Wrappers.<DrillAnnualEmergency>lambdaQuery()
                .eq(DrillAnnualEmergency::getPlanYear, year)
                .eq(DrillAnnualEmergency::getPlanMonth, month)
                .eq(DrillAnnualEmergency::getIsDel, DeletedEnum.VALID.getValue()));
        List<DrillPlan> drillPlans = this.list(Wrappers.<DrillPlan>lambdaQuery()
                .eq(DrillPlan::getPlanYear, year)
                .eq(DrillPlan::getPlanMonth, month)
                .eq(DrillPlan::getIsDel, DeletedEnum.VALID.getValue()));
        for (DrillAnnualEmergency drillAnnualEmergency : list) {
            List<DrillPlan> plans = drillPlans.stream().filter(li ->
                    Objects.equals(li.getDrillType(), drillAnnualEmergency.getId())
                            && Objects.equals(li.getPlanYear(), drillAnnualEmergency.getPlanYear())
                            && Objects.equals(li.getPlanMonth(), drillAnnualEmergency.getPlanMonth())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(plans)) {
                if (Objects.equals(1, day) || Objects.equals(15, day) || Objects.equals(25, day)) {
                    // 发送未录入演习消息 规则：1、15、25日校验
                    AppLogin appLogin = appLoginService.selectAppLoginByUserId(Long.valueOf(drillAnnualEmergency.getDirectorBy()));
                    if (Objects.nonNull(appLogin)) {
                        sysNoticeService.insertNoticeToUser(appLogin.getId(), drillAnnualEmergency.getPlanName() + "未录入演习，请录入", SysNoticeTitleRouteEnum.DRILL_MSG);
                    }
                }
            } else {
                //指定获取需要获取的时间点
                Calendar calendar1 = Calendar.getInstance();
                calendar1.setTime(new Date());
                // 将时分秒,毫秒域清零
                calendar1.set(Calendar.HOUR_OF_DAY, 0);
                calendar1.set(Calendar.MINUTE, 0);
                calendar1.set(Calendar.SECOND, 0);
                calendar1.set(Calendar.MILLISECOND, 0);
                Date date = calendar1.getTime();
                for (DrillPlan plan : plans) {
                    if (Objects.equals(plan.getDrillStatus(), DrillEnum.DRILL_STATUS_YES.getValue())) {
                        continue;
                    }
                    if (plan.getPlanStartTime().compareTo(calculationTime(date, Calendar.DATE, -1)) >= 0
                            && date.compareTo(plan.getPlanStartTime()) > 0) {
                        Long organizer = plan.getDrillOrganizer();
                        AppLogin appLogin = appLoginService.selectAppLoginByUserId(organizer);
                        if (Objects.nonNull(appLogin)) {
                            // 发送未演习消息
                            sysNoticeService.insertNoticeToUser(appLogin.getId(), plan.getDrillName() + "还未演习，请按时演习", SysNoticeTitleRouteEnum.DRILL_MSG);
                        }
                    }
                }
            }
        }

        return AjaxResult.success();
    }

    /**
     * APP获取演习计划详情
     * 添加权限校验，领导时需要判断当前账号是否为演习组织人
     *
     * @param id          演习计划ID
     * @param drillStatus 演习状态：1-未完成；2-已完成(drill_plan)
     * @return
     */
    @Override
    public AjaxResult getInfo(String id, Long drillStatus) {
        DrillPlan drillPlan = this.getById(id);
        //因为领导查看全部，需要判断他是否为组织人
        // 获取app账号对应的pc的userId
        String pcUserId = JWTUtil.getPCUserId();
        if (StringUtils.isEmpty(pcUserId)) {
            return AjaxResult.warn("当前账号无法进行演习，请切换演习组织人账号操作！");
        }

        String requestToken = JWTUtil.getRequestToken();
        String appUserType = null;
        try {
            appUserType = JWTUtil.getAppUserType();
        } catch (Exception e) {

        }
        //承包商不让查看，直接返回空集合
        if (appUserType != null && AppUserTypeEnum.CONTRACTOR.getValue() == Integer.parseInt(appUserType)) {
            return AjaxResult.warn("当前账号无法进行演习，请切换演习组织人账号操作！");
        }
        // APP请求时：未完成时才校验是否为组织人
        else if (StringUtils.isNotBlank(requestToken) && drillStatus == DrillEnum.DRILL_STATUS_NO.getValue()) {
            boolean leader = JWTUtil.isLeader();
            // 领导时检查是否为演习组织人
            if (leader) {
                //设置组织人为当前登录人
//                drillPlan.setDrillOrganizer(Long.parseLong(pcUserId));
//                LambdaQueryWrapper<DrillPlan> wrapper = Wrappers.lambdaQuery();
//                wrapper.eq(DrillPlan::getId, id);//演习计划ID
//                wrapper.eq(DrillPlan::getDrillOrganizer, drillPlan.getDrillOrganizer());//演习组织人
//                wrapper.eq(DrillPlan::getIsDel, DeletedEnum.VALID.getValue());
//                List<DrillPlan> drillPlans = this.list(wrapper);
//                if(CollectionUtils.isEmpty(drillPlans)) {
//                    return AjaxResult.warn("当前账号无法进行演习，请切换演习组织人账号操作！");
//                }
                Long drillOrganizerDB = drillPlan.getDrillOrganizer();
                if (drillOrganizerDB != Long.parseLong(pcUserId)) {
                    return AjaxResult.warn("当前账号无法进行演习，请切换演习组织人账号操作！");
                }
            }
        }


        if (Objects.isNull(drillPlan) && drillPlan.getIsDel() == DeletedEnum.VALID.getValue()) {
            return AjaxResult.warn("暂无数据");
        }

        DrillPlanResultDto dto = new DrillPlanResultDto();
        BeanUtils.copyProperties(drillPlan, dto);
        List<DrillProcess> drillProcessList = drillProcessService.list(Wrappers.<DrillProcess>lambdaQuery()
                .eq(DrillProcess::getPlanId, id)
                .orderByAsc(DrillProcess::getSortdNum));
        List<DrillProcessDto> drillProcessDtos = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(drillProcessList)) {
            for (DrillProcess dp : drillProcessList) {
                DrillProcessDto entry = new DrillProcessDto();
                BeanUtils.copyProperties(dp, entry);
                entry.setConfirmByName(getSysUserNameById(dp.getConfirmBy()));
                drillProcessDtos.add(entry);
            }
            dto.setDrillProcessList(drillProcessDtos);
        }

        List<DrillPerson> drillPersonList = drillPersonService.list(Wrappers.<DrillPerson>lambdaQuery().eq(DrillPerson::getPlanId, id));
        dto.setDrillPersonList(drillPersonList);

        List<DrillRectificationProblems> drillRectificationProblemsList = drillRectificationProblemsService.list(Wrappers.<DrillRectificationProblems>lambdaQuery()
                .eq(DrillRectificationProblems::getPlanId, id)
                .orderByAsc(DrillRectificationProblems::getSortdNum));
        List<DrillRectificationProblemsDto> drillRectificationProblemsDtos = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(drillRectificationProblemsList)) {
            for (DrillRectificationProblems drp : drillRectificationProblemsList) {
                DrillRectificationProblemsDto entry = new DrillRectificationProblemsDto();
                BeanUtils.copyProperties(drp, entry);
                entry.setRectificationByName(getSysUserNameById(drp.getRectificationBy()));
                entry.setPersonLiableName(getSysUserNameById(drp.getPersonLiable()));
                drillRectificationProblemsDtos.add(entry);
            }
            dto.setDrillRectificationProblemsList(drillRectificationProblemsDtos);
        }

        List<DrillPic> drillPicList = drillPicService.list(Wrappers.<DrillPic>lambdaQuery()
                .eq(DrillPic::getPlanId, id));
        dto.setDrillPicList(drillPicList);

        dto.setDrillTypeName(

                getDrillTypeConfigurationNameById(dto.getDrillType()));
        dto.setDrillOrganizerName(

                getSysUserNameById(dto.getDrillOrganizer()));
        dto.setDrillDepartmentName(

                getSysDeptNameById(dto.getDrillDepartment()));

        if (StringUtils.isNotEmpty(drillPlan.getDrillDepartments())) {
            dto.setDrillDepartmentsList(Arrays.asList(drillPlan.getDrillDepartments().split(",")));
        }

        return AjaxResult.success(dto);
    }

    /**
     * PC获取演习计划详情
     *
     * @param id
     * @return
     */
    @Override
    public AjaxResult getInfoPC(String id) {
        DrillPlanResultDto dto = new DrillPlanResultDto();
        DrillPlan drillPlan = this.getById(id);
        if (Objects.isNull(drillPlan)) {
            return AjaxResult.warn("暂无数据");
        }
        BeanUtils.copyProperties(drillPlan, dto);
        List<DrillProcess> drillProcessList = drillProcessService.list(Wrappers.<DrillProcess>lambdaQuery()
                .eq(DrillProcess::getPlanId, id)
                .orderByAsc(DrillProcess::getSortdNum));
        List<DrillProcessDto> drillProcessDtos = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(drillProcessList)) {
            for (DrillProcess dp : drillProcessList) {
                DrillProcessDto entry = new DrillProcessDto();
                BeanUtils.copyProperties(dp, entry);
                entry.setConfirmByName(getSysUserNameById(dp.getConfirmBy()));
                drillProcessDtos.add(entry);
            }
            dto.setDrillProcessList(drillProcessDtos);
        }

        List<DrillPerson> drillPersonList = drillPersonService.list(Wrappers.<DrillPerson>lambdaQuery().eq(DrillPerson::getPlanId, id));
        dto.setDrillPersonList(drillPersonList);

        List<DrillRectificationProblems> drillRectificationProblemsList = drillRectificationProblemsService.list(Wrappers.<DrillRectificationProblems>lambdaQuery()
                .eq(DrillRectificationProblems::getPlanId, id)
                .orderByAsc(DrillRectificationProblems::getSortdNum));
        List<DrillRectificationProblemsDto> drillRectificationProblemsDtos = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(drillRectificationProblemsList)) {
            for (DrillRectificationProblems drp : drillRectificationProblemsList) {
                DrillRectificationProblemsDto entry = new DrillRectificationProblemsDto();
                BeanUtils.copyProperties(drp, entry);
                entry.setRectificationByName(getSysUserNameById(drp.getRectificationBy()));
                entry.setPersonLiableName(getSysUserNameById(drp.getPersonLiable()));
                drillRectificationProblemsDtos.add(entry);
            }
            dto.setDrillRectificationProblemsList(drillRectificationProblemsDtos);
        }

        List<DrillPic> drillPicList = drillPicService.list(Wrappers.<DrillPic>lambdaQuery()
                .eq(DrillPic::getPlanId, id));
        dto.setDrillPicList(drillPicList);

        dto.setDrillTypeName(getDrillTypeConfigurationNameById(dto.getDrillType()));
        dto.setDrillOrganizerName(getSysUserNameById(dto.getDrillOrganizer()));
        dto.setDrillDepartmentName(getSysDeptNameById(dto.getDrillDepartment()));

        if (StringUtils.isNotEmpty(drillPlan.getDrillDepartments())) {
            dto.setDrillDepartmentsList(Arrays.asList(drillPlan.getDrillDepartments().split(",")));
        }

        return AjaxResult.success(dto);
    }

    private String getDrillTypeConfigurationNameById(String id) {
        DrillAnnualEmergency typeInfo = drillAnnualEmergencyService.getById(id);
        return Objects.nonNull(typeInfo) ? typeInfo.getPlanName() : "";
    }

    private String getSysUserNameById(Long id) {
        SysUser sysUser = getSysUserById(id);
        return Objects.nonNull(sysUser) ? sysUser.getNickName() : "";
    }

    private SysUser getSysUserById(Long id) {
        return userService.selectUserById(id);
    }

    private String getSysDeptNameById(Long id) {
        SysDept sysDept = getSysDeptById(id);
        return Objects.nonNull(sysDept) ? sysDept.getDeptName() : "";
    }

    private SysDept getSysDeptById(Long id) {
        return deptService.selectDeptById(id);
    }

    @Override
    public List<DrillPlanListDto> findList(DrillPlan drillPlan) {
        LambdaQueryWrapper<DrillPlan> wrapper = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(drillPlan.getDrillSn())) {
            wrapper.like(DrillPlan::getDrillSn, drillPlan.getDrillSn());
        }
        if (StringUtils.isNotBlank(drillPlan.getDrillName())) {
            wrapper.like(DrillPlan::getDrillName, drillPlan.getDrillName());
        }
        if (Objects.nonNull(drillPlan.getDrillOrganizer())) {
            wrapper.eq(DrillPlan::getDrillOrganizer, drillPlan.getDrillOrganizer());
        }
        String drillType = drillPlan.getDrillType();
        if (StringUtils.isNotBlank(drillType)) {
            List<DrillAnnualEmergency> list = drillAnnualEmergencyService.list(Wrappers.<DrillAnnualEmergency>lambdaQuery()
                    .eq(DrillAnnualEmergency::getPlanName, drillType));
            List<String> collect = list.stream().map(DrillAnnualEmergency::getId).collect(Collectors.toList());
            wrapper.in(DrillPlan::getDrillType, collect);
        }
        if (Objects.nonNull(drillPlan.getDrillStatus())) {
            wrapper.eq(DrillPlan::getDrillStatus, drillPlan.getDrillStatus());
        }
        if (Objects.nonNull(drillPlan.getProcessStatus())) {
            wrapper.eq(DrillPlan::getProcessStatus, drillPlan.getProcessStatus());
        }
        wrapper.eq(DrillPlan::getIsDel, DeletedEnum.VALID.getValue());
        wrapper.orderByDesc(DrillPlan::getCreateDate);
        wrapper.orderByDesc(DrillPlan::getUpdateDate);
        List<DrillPlan> drillPlans = this.list(wrapper);
        List<DrillPlanListDto> list = new ArrayList<>();
        for (DrillPlan plan : drillPlans) {
            DrillPlanListDto dto = new DrillPlanListDto();
            BeanUtils.copyProperties(plan, dto);

            dto.setDrillTypeName(getDrillTypeConfigurationNameById(dto.getDrillType()));
            dto.setDrillOrganizerName(getSysUserNameById(dto.getDrillOrganizer()));
            dto.setDrillDepartmentName(getSysDeptNameById(dto.getDrillDepartment()));
            dto.setProcessByName(getSysUserNameById(dto.getProcessBy()));

            list.add(dto);
        }
        return list;
    }

    @Override
    @Transactional
    public AjaxResult removePlan(String ids) {
        this.removeById(ids);
        drillPersonService.remove(Wrappers.<DrillPerson>lambdaQuery().eq(DrillPerson::getPlanId, ids));
        drillPicService.remove(Wrappers.<DrillPic>lambdaQuery().eq(DrillPic::getPlanId, ids));
        drillProcessService.remove(Wrappers.<DrillProcess>lambdaQuery().eq(DrillProcess::getPlanId, ids));
        drillRectificationProblemsService.remove(Wrappers.<DrillRectificationProblems>lambdaQuery().eq(DrillRectificationProblems::getPlanId, ids));
        return AjaxResult.success();
    }

    /**
     * 获取演习编号
     *
     * @return 演习编号
     * @author matianxiang
     * @date 2023/8/8 18:42
     */
    private String getDrillSn() {
        // 格式：YJGL2023001
        Calendar calendar = Calendar.getInstance();
        String key = "drillPlanSn:" + calendar.get(Calendar.YEAR);
        long incr = redisCache.incr(key, 1L);
        // 有效期一年
        redisCache.expire(key, 366, TimeUnit.DAYS);
        String sn = String.format("%03d", incr);
        return "YJGL" + calendar.get(Calendar.YEAR) + sn;
    }

    /**
     * 计算时间
     *
     * @param oldDate 原始时间
     * @param unit    单位
     * @param num     数量 加日期用正数，减日期用负数
     * @return R
     * @author mtx
     * @date 2022/11/9 20:16
     */
    public Date calculationTime(Date oldDate, int unit, int num) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(oldDate);
        ca.add(unit, num);
        return ca.getTime();
    }
}
