package com.yuchen.saas.park.service.service.fire.inspect.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.thinkunion.park.service.common.utils.ReceiptCodeUtil;
import com.yuchen.saas.manage.system.api.entity.Dept;
import com.yuchen.saas.manage.system.api.entity.NestOrgRole;
import com.yuchen.saas.manage.system.api.entity.NestOrgRoleBinding;
import com.yuchen.saas.manage.system.api.entity.NestOrgUser;
import com.yuchen.saas.manage.system.api.feign.DeptFeignServer;
import com.yuchen.saas.manage.system.api.feign.IOrgRoleClient;
import com.yuchen.saas.manage.system.api.feign.IOrgUserClient;
import com.yuchen.saas.manage.user.api.entity.UserDept;
import com.yuchen.saas.manage.user.api.feign.IUserDeptClient;
import com.yuchen.saas.park.api.dto.NoModelWriteDataDTO;
import com.yuchen.saas.park.api.dto.fire.inspect.plan.*;
import com.yuchen.saas.park.api.entity.fire.inspect.*;
import com.yuchen.saas.park.api.enums.inspect.PlanExecuteStateEnum;
import com.yuchen.saas.park.api.enums.inspect.TaskStateEnum;
import com.yuchen.saas.park.api.enums.inspect.WeekEnum;
import com.yuchen.saas.park.api.vo.fire.inspect.plan.FireInspectPlanDetailVO;
import com.yuchen.saas.park.api.vo.fire.inspect.plan.FireInspectPlanTaskTableVO;
import com.yuchen.saas.park.api.vo.fire.inspect.plan.FireInspectPlanVO;
import com.yuchen.saas.park.service.mapper.fire.inspect.SaasParkFireInspectPlanMapper;
import com.yuchen.saas.park.service.service.fire.inspect.*;
import com.yuchen.saas.park.service.util.ExcelUtils;
import com.yuchen.saas.park.service.util.PageConverterUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nest.springwrap.core.log.exception.ServiceException;
import org.nest.springwrap.core.mp.base.BaseEntity;
import org.nest.springwrap.core.mp.base.BaseServiceImpl;
import org.nest.springwrap.core.mp.support.Condition;
import org.nest.springwrap.core.mp.support.NestPage;
import org.nest.springwrap.core.mp.support.Query;
import org.nest.springwrap.core.secure.ContextUser;
import org.nest.springwrap.core.secure.utils.AuthUtil;
import org.nest.springwrap.core.tool.utils.DateUtil;
import org.nest.springwrap.core.tool.utils.Func;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 巡检计划表 服务实现类
 * </p>
 *
 * @author zhouhanwei
 * @since 2024-04-03
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SaasParkFireInspectPlanServiceImpl extends BaseServiceImpl<SaasParkFireInspectPlanMapper, SaasParkFireInspectPlan> implements ISaasParkFireInspectPlanService {

    private final IOrgUserClient iOrgUserClient;

    private final IUserDeptClient iUserDeptClient;

    private final IOrgRoleClient iOrgRoleClient;

    private final DeptFeignServer deptFeignServer;

    private final ISaasParkFireInspectPlanConfigService planConfigService;

    private final ISaasParkFireInspectPlanTaskService planTaskService;

    private final ISaasParkFireInspectTypeService inspectTypeService;

    @Override
    public NestPage<FireInspectPlanVO> findFireInspectPlanPage(FireInspectPlanReqDTO reqDTO) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Objects.isNull(contextUser)) {
            throw new ServiceException("用户不存在");
        }
        Page<FireInspectPlanVO> resultPage = new Page<>();
        // 赋值数据
        LambdaQueryWrapper<SaasParkFireInspectPlan> lambdaWrapper = Wrappers.lambdaQuery();
        lambdaWrapper.eq(SaasParkFireInspectPlan::getCustomerId, contextUser.getCustomerManageId());
        lambdaWrapper.eq(Func.isNotEmpty(reqDTO.getBusinessId()), SaasParkFireInspectPlan::getBusinessId, reqDTO.getBusinessId());
        lambdaWrapper.eq(Func.isNotEmpty(reqDTO.getProjectId()), SaasParkFireInspectPlan::getProjectId, reqDTO.getProjectId());
        lambdaWrapper.eq(Func.isNotEmpty(reqDTO.getInspectTypeId()), SaasParkFireInspectPlan::getInspectTypeId, reqDTO.getInspectTypeId());
        lambdaWrapper.eq(Func.isNotEmpty(reqDTO.getPlanState()), SaasParkFireInspectPlan::getPlanState, reqDTO.getPlanState());
        lambdaWrapper.like(Func.isNotEmpty(reqDTO.getInspectPlanName()), SaasParkFireInspectPlan::getInspectPlanName, reqDTO.getInspectPlanName());
        lambdaWrapper.orderByDesc(BaseEntity::getCreateTime);
        IPage<SaasParkFireInspectPlan> page = page(Condition.getPage(reqDTO),lambdaWrapper);
        List<SaasParkFireInspectPlan> fireInspectPlanList = page.getRecords();
        // 返回数据列表
        List<FireInspectPlanVO> resultList = new ArrayList<>();
        if (CollUtil.isEmpty(fireInspectPlanList)) {
            resultPage.setTotal(page.getTotal());
            resultPage.setSize(page.getSize());
            resultPage.setCurrent(page.getCurrent());
            resultPage.setRecords(resultList);
            return PageConverterUtils.convert(resultPage);
        }
        List<Long> typeIds = fireInspectPlanList.stream().map(SaasParkFireInspectPlan::getInspectTypeId).collect(Collectors.toList());
        Map<Long, String> inspectTypeMap = inspectTypeService.findFireInspectTypeMap(typeIds);

        for (SaasParkFireInspectPlan saasParkFireInspectPlan : fireInspectPlanList) {
            FireInspectPlanVO vo = new FireInspectPlanVO();
            BeanUtil.copyProperties(saasParkFireInspectPlan, vo);
            vo.setInspectTypeName(inspectTypeMap.get(vo.getInspectTypeId()));
            resultList.add(vo);
        }
        resultPage.setTotal(page.getTotal());
        resultPage.setSize(page.getSize());
        resultPage.setCurrent(page.getCurrent());
        resultPage.setRecords(resultList);
        return PageConverterUtils.convert(resultPage);
    }

    @Override
    public FireInspectPlanDetailVO getFireInspectPlan(Long planId) {
        SaasParkFireInspectPlan saasParkFireInspectPlan = getById(planId);
        if (Objects.isNull(saasParkFireInspectPlan)) {
            throw new ServiceException("巡检计划数据不存在");
        }
        FireInspectPlanDetailVO vo = new FireInspectPlanDetailVO();
        BeanUtil.copyProperties(saasParkFireInspectPlan, vo);
        NestOrgUser nestOrgUser = iOrgUserClient.detail(vo.getCreateOrgUser()).getData();
        if (Objects.nonNull(nestOrgUser)) {
            vo.setOrgUserName(nestOrgUser.getName());
        }
        // 巡检点配置
        List<SaasParkFireInspectPlanConfig> planConfigList = planConfigService.list(new LambdaQueryWrapper<SaasParkFireInspectPlanConfig>()
                .eq(SaasParkFireInspectPlanConfig::getTaskPlanId, planId)
                .orderByAsc(SaasParkFireInspectPlanConfig::getSort));
//        // 巡检点id列表
//        List<Long> inspectConfigIdList = planConfigList.stream().map(SaasParkFireInspectPlanConfig::getInspectConfigId).collect(Collectors.toList());
//        // 巡检表单id列表
//        List<Long> inspectFormIdList = planConfigList.stream().map(SaasParkFireInspectPlanConfig::getInspectFormId).collect(Collectors.toList());
//        // 巡检点配置列表
//        List<SaasParkFireInspectConfig> inspectConfigList = inspectConfigService.listByIds(inspectConfigIdList);
//        Map<Long, String> inspectConfigMap = inspectConfigList.stream().collect(Collectors.toMap(BaseEntity::getId, SaasParkFireInspectConfig::getInspectConfigName));
//        // 巡检表单列表
//        List<SaasParkFireInspectForm> inspectFormList = inspectFormService.listByIds(inspectFormIdList);
//        Map<Long, String> inspectFormMap = inspectFormList.stream().collect(Collectors.toMap(BaseEntity::getId, SaasParkFireInspectForm::getInspectTitle));

        vo.setPlanConfigDTOList(planConfigList.stream().map(s->{
            FireInspectPlanConfigDTO planConfigDTO = new FireInspectPlanConfigDTO();
            BeanUtil.copyProperties(s, planConfigDTO);
//            planConfigDTO.setInspectConfigName(inspectConfigMap.get(planConfigDTO.getInspectConfigId()));
//            planConfigDTO.setInspectFormName(inspectFormMap.get(planConfigDTO.getInspectFormId()));
            return planConfigDTO;
        }).collect(Collectors.toList()));
        switch (vo.getInspectPeopleType()) {
            // 巡检人类型为成员
            case "1":
                List<Long> orgUserIdList = Arrays.stream(vo.getInspectPeopleIds().split(","))
                        .map(Long::parseLong).collect(Collectors.toList());
                List<NestOrgUser> feignResult = iOrgUserClient.findOrgUserListByIds(orgUserIdList).getData();
                List<String> orgUserNameList = feignResult.stream().map(NestOrgUser::getName).collect(Collectors.toList());
                vo.setInspectPeopleNames(CollUtil.join(orgUserNameList, ","));
                break;
            // 巡检人类型为部门
            case "2":
                // 获取部门名称
                Dept dept = deptFeignServer.getDept(vo.getDeptRoleId()).getData();
                if (Objects.nonNull(dept) && StrUtil.isNotBlank(dept.getDeptName())) {
                    vo.setDeptRoleName(dept.getDeptName());
                }
                break;
            // 巡检人类型为角色
            case "3":
                // 获取角色下的成员列表
                NestOrgRole nestOrgRole = iOrgRoleClient.getOrgRoleById(vo.getDeptRoleId()).getData();
                if (Objects.nonNull(nestOrgRole) && StrUtil.isNotBlank(nestOrgRole.getName())) {
                    vo.setDeptRoleName(nestOrgRole.getName());
                }
                break;
        }

        return vo;
    }

    @Override
    public FireInspectPlanTaskTableVO getPlanTaskTable(Long planId) {
        SaasParkFireInspectPlan saasParkFireInspectPlan = getById(planId);
        if (Objects.isNull(saasParkFireInspectPlan)) {
            throw new ServiceException("巡检计划数据不存在");
        }
        // 获取任务表格
        FireInspectPlanTaskTableVO taskTableVO = new FireInspectPlanTaskTableVO();
        taskTableVO.setHeadDateList(JSONArray.parseArray(saasParkFireInspectPlan.getTaskHeadData(), String.class));
        // 生成表内容
        List<List<FireInspectPlanTaskTableVO.OrgUserData>> contentDataList = new ArrayList<>();
        JSONArray jsonArray = JSONArray.parseArray(saasParkFireInspectPlan.getTaskContentData());
        // 所有表组织用户
        List<Long> orgUserIdAllList = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONArray jsonCell = jsonArray.getJSONArray(i);
            List<FireInspectPlanTaskTableVO.OrgUserData> orgUserDataList = jsonCell.toJavaList(FireInspectPlanTaskTableVO.OrgUserData.class);
            for (int j = 0; j < orgUserDataList.size(); j++) {
                if (j == 0) {
                    continue;
                }
                FireInspectPlanTaskTableVO.OrgUserData orgUserData = orgUserDataList.get(j);
                orgUserIdAllList.addAll(orgUserData.getOrgUserIdList());
            }
            contentDataList.add(orgUserDataList);
        }
        // 获取选中的组织成员列表
        List<NestOrgUser> orgUserList = iOrgUserClient.findOrgUserListByIds(orgUserIdAllList.stream().distinct().collect(Collectors.toList())).getData();
        Map<Long, String> orgUserMap = orgUserList.stream().collect(Collectors.toMap(BaseEntity::getId, NestOrgUser::getName));
        for (List<FireInspectPlanTaskTableVO.OrgUserData> orgUserDataList : contentDataList) {
            for (int j = 0; j < orgUserDataList.size(); j++) {
                if (j == 0) {
                    continue;
                }
                FireInspectPlanTaskTableVO.OrgUserData orgUserData = orgUserDataList.get(j);
                List<Long> orgUserIdList = orgUserData.getOrgUserIdList();
                List<String> orgUserNameList = new ArrayList<>();
                for (Long orgUserId : orgUserIdList) {
                    orgUserNameList.add(orgUserMap.get(orgUserId));
                }
                orgUserData.setOrgUserNames(CollUtil.join(orgUserNameList, ","));
            }
        }
        taskTableVO.setContentDataList(contentDataList);
        return taskTableVO;
    }

    @Override
    public Boolean closePlan(Long planId) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Objects.isNull(contextUser)) {
            throw new ServiceException("用户不存在");
        }
        SaasParkFireInspectPlan saasParkFireInspectPlan = getById(planId);
        if (Objects.isNull(saasParkFireInspectPlan)) {
            throw new ServiceException("巡检计划数据不存在");
        }
        saasParkFireInspectPlan.setPlanState(PlanExecuteStateEnum.ClOSE.getCode());
        saasParkFireInspectPlan.setUpdateOrgUser(contextUser.getOrgUserId());
        return updateById(saasParkFireInspectPlan);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addInspectPlan(FireInspectPlanSubmitReqDTO reqDTO) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Objects.isNull(contextUser)) {
            throw new ServiceException("用户不存在");
        }
        // 校验入参
        verifySubmitParam(reqDTO);
        // 巡检计划信息
        SaasParkFireInspectPlan saasParkFireInspectPlan = new SaasParkFireInspectPlan();
        saasParkFireInspectPlan.setCustomerId(contextUser.getCustomerManageId());
        saasParkFireInspectPlan.setProjectId(reqDTO.getProjectId());
        saasParkFireInspectPlan.setInspectTypeId(reqDTO.getInspectTypeId());
        saasParkFireInspectPlan.setInspectPlanName(reqDTO.getInspectPlanName());
        saasParkFireInspectPlan.setPlanState(PlanExecuteStateEnum.TO_EXECUTE.getCode());
        saasParkFireInspectPlan.setPlanStartDate(reqDTO.getPlanStartDate());
        saasParkFireInspectPlan.setPlanEndDate(reqDTO.getPlanEndDate());
        saasParkFireInspectPlan.setCreateOrgUser(contextUser.getOrgUserId());
        saasParkFireInspectPlan.setUpdateOrgUser(contextUser.getOrgUserId());
        // 获取任务数
        int taskNum = 0;
        for (List<FireInspectPlanTaskTableVO.OrgUserData> orgUserDataList : reqDTO.getContentDataList()) {
            taskNum += orgUserDataList.size() - 1;
        }
        saasParkFireInspectPlan.setTaskNum(taskNum);
        // 获取时间段
        List<String> periodValueList = new ArrayList<>();
        for (PlanTimePeriodValueDTO valueDTO : reqDTO.getPlanTimePeriodValueDTOList()) {
            String periodValue;
            if (valueDTO.getTimePeriod() > 0) {
                periodValue = valueDTO.getPlanStartTimePeriod() + "~" + valueDTO.getPlanEndTimePeriod() + "(+" + valueDTO.getTimePeriod() + "天)";
            } else {
                periodValue = valueDTO.getPlanStartTimePeriod() + "~" + valueDTO.getPlanEndTimePeriod();
            }

            periodValueList.add(periodValue);
        }
        saasParkFireInspectPlan.setPlanTimePeriodData(JSONArray.toJSONString(reqDTO.getPlanTimePeriodValueDTOList()));
        saasParkFireInspectPlan.setPlanTimePeriodValue(CollUtil.join(periodValueList, "、"));
        saasParkFireInspectPlan.setInspectPeopleType(reqDTO.getInspectPeopleType());
        saasParkFireInspectPlan.setDeptRoleId(reqDTO.getDeptRoleId());
        saasParkFireInspectPlan.setInspectPeopleIds(CollUtil.join(reqDTO.getOrgUserIdList(), ","));
        saasParkFireInspectPlan.setPlanRuleCycle(reqDTO.getPlanRuleCycle());
        saasParkFireInspectPlan.setPlanRuleCycleValue(CollUtil.join(reqDTO.getPlanRuleCycleValue(), ","));
        saasParkFireInspectPlan.setDistributionMode(reqDTO.getDistributionMode());
        // 任务表头
        saasParkFireInspectPlan.setTaskHeadData(JSONArray.toJSONString(reqDTO.getHeadDateList()));
        saasParkFireInspectPlan.setTaskContentData(JSONArray.toJSONString(reqDTO.getContentDataList()));
        // 任务要求
        saasParkFireInspectPlan.setTaskStartNotifyDemand(reqDTO.getTaskStartNotifyDemand());
        saasParkFireInspectPlan.setTaskStartNotify(reqDTO.getTaskStartNotify());
        saasParkFireInspectPlan.setTaskStartNotifyType(reqDTO.getTaskStartNotifyType());
        saasParkFireInspectPlan.setTaskEndNotifyDemand(reqDTO.getTaskEndNotifyDemand());
        saasParkFireInspectPlan.setTaskEndNotify(reqDTO.getTaskEndNotify());
        saasParkFireInspectPlan.setTaskEndNotifyType(reqDTO.getTaskStartNotifyType());
        saasParkFireInspectPlan.setTaskAutoCloseDemand(reqDTO.getTaskAutoCloseDemand());
        saasParkFireInspectPlan.setTaskOutAllowDemand(reqDTO.getTaskOutAllowDemand());
        saasParkFireInspectPlan.setTaskSequenceDemand(reqDTO.getTaskSequenceDemand());
        saasParkFireInspectPlan.setTaskPhotoDemand(reqDTO.getTaskPhotoDemand());
        // 任务执行模式
        saasParkFireInspectPlan.setTaskExecuteType(reqDTO.getTaskExecuteType());
        saasParkFireInspectPlan.setRemark(reqDTO.getRemark());
        // 名字去重
        validRepeat(saasParkFireInspectPlan);
        // 保存巡检计划信息
        save(saasParkFireInspectPlan);
        // 计划巡检点
        List<SaasParkFireInspectPlanConfig> planConfigList = new ArrayList<>();
        for (FireInspectPlanConfigDTO planConfigDTO : reqDTO.getPlanConfigDTOList()) {
            SaasParkFireInspectPlanConfig planConfig = new SaasParkFireInspectPlanConfig();
            BeanUtil.copyProperties(planConfigDTO, planConfig);
            planConfig.setCustomerId(saasParkFireInspectPlan.getCustomerId());
            planConfig.setTaskPlanType("1");
            planConfig.setTaskPlanId(saasParkFireInspectPlan.getId());
            planConfig.setCreateOrgUser(contextUser.getOrgUserId());
            planConfigList.add(planConfig);
        }
        // 保存计划巡检点
        planConfigService.saveBatch(planConfigList);

        Date newDate = new Date();
        // 任务巡检点
        List<SaasParkFireInspectPlanConfig> taskConfigList = new ArrayList<>();
        for (List<FireInspectPlanTaskTableVO.OrgUserData> orgUserDataList : reqDTO.getContentDataList()) {
            String startPeriod = null;
            String endPeriod = null;
            int period = 0;
            for (int i = 0; i < orgUserDataList.size(); i++) {
                if (i == 0) {
                    PlanTimePeriodValueDTO timePeriodValue = orgUserDataList.get(i).getPeriodValueDTO();
                    startPeriod = timePeriodValue.getPlanStartTimePeriod() + ":00";
                    endPeriod = timePeriodValue.getPlanEndTimePeriod() + ":00";
                    period = timePeriodValue.getTimePeriod();
                    continue;
                }
                FireInspectPlanTaskTableVO.OrgUserData orgUserData = orgUserDataList.get(i);
                SaasParkFireInspectPlanTask planTask = new SaasParkFireInspectPlanTask();
                planTask.setCustomerId(saasParkFireInspectPlan.getCustomerId());
                planTask.setProjectId(saasParkFireInspectPlan.getProjectId());
                planTask.setInspectTypeId(saasParkFireInspectPlan.getInspectTypeId());
                planTask.setReceiptCode(ReceiptCodeUtil.setReceiptCodeValue("XJRW"));
                planTask.setPlanId(saasParkFireInspectPlan.getId());
                planTask.setTaskType("1");
                planTask.setTaskName(saasParkFireInspectPlan.getInspectPlanName());
                // 任务日期
                planTask.setTaskDate(DateUtil.parse(orgUserData.getTaskDate(), DateUtil.PATTERN_DATE));
                String taskStartTime = orgUserData.getTaskDate() + " " + startPeriod;
                planTask.setTaskStartTime(DateUtil.parse(taskStartTime, DateUtil.PATTERN_DATETIME));
                String taskEndTime = orgUserData.getTaskDate() + " " + endPeriod;
                Date endTime = DateUtil.parse(taskEndTime, DateUtil.PATTERN_DATETIME);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(endTime);
                // 增加period天
                calendar.add(Calendar.DATE, period);
                planTask.setTaskEndTime(calendar.getTime());
                planTask.setPlanTimePeriodValue(saasParkFireInspectPlan.getPlanTimePeriodValue());
                planTask.setInspectNum(planConfigList.size());
                planTask.setInspectedNum(0);
                planTask.setTaskState(TaskStateEnum.TO_START.getCode());
                if (planTask.getTaskStartTime().getTime() >= planTask.getTaskEndTime().getTime()) {
                    throw new ServiceException("任务开始时间不能大于任务结束时间");
                }
                if (newDate.getTime() <= planTask.getTaskEndTime().getTime()) {
                    planTask.setExecuteState(PlanExecuteStateEnum.EXECUTING.getCode());
                } else {
                    planTask.setExecuteState(PlanExecuteStateEnum.OUT_NO_INSPECT.getCode());
//                    throw new ServiceException("任务结束时间不能小于当前时间");
                }
                // 有开启任务通知任务通知时间赋值
                if ("1".equals(reqDTO.getTaskStartNotifyDemand())) {
                    setTaskNotifyTimeValue(planTask, reqDTO);
                }
                setTaskOutTimeValue(planTask, reqDTO);
                // 任务处理人列表
                List<Long> peopleIds = orgUserData.getOrgUserIdList();
                planTask.setInspectPeopleIds(CollUtil.join(peopleIds, ","));
                planTask.setTaskPeopleIds(CollUtil.join(peopleIds, ","));
                // 任务要求
                planTask.setTaskStartNotifyDemand(reqDTO.getTaskStartNotifyDemand());
                planTask.setTaskStartNotify(reqDTO.getTaskStartNotify());
                planTask.setTaskStartNotifyType(reqDTO.getTaskStartNotifyType());
                planTask.setTaskEndNotifyDemand(reqDTO.getTaskEndNotifyDemand());
                planTask.setTaskEndNotify(reqDTO.getTaskEndNotify());
                planTask.setTaskEndNotifyType(reqDTO.getTaskStartNotifyType());
                planTask.setTaskAutoCloseDemand(reqDTO.getTaskAutoCloseDemand());
                planTask.setTaskOutAllowDemand(reqDTO.getTaskOutAllowDemand());
                planTask.setTaskSequenceDemand(reqDTO.getTaskSequenceDemand());
                planTask.setTaskPhotoDemand(reqDTO.getTaskPhotoDemand());
                // 任务执行模式
                planTask.setTaskExecuteType(reqDTO.getTaskExecuteType());
                planTask.setCreateOrgUser(saasParkFireInspectPlan.getCreateOrgUser());
                // 创建任务
                planTaskService.save(planTask);
                int sort = 1;
                for (FireInspectPlanConfigDTO planConfigDTO : reqDTO.getPlanConfigDTOList()) {
                    SaasParkFireInspectPlanConfig planConfig = new SaasParkFireInspectPlanConfig();
                    BeanUtil.copyProperties(planConfigDTO, planConfig);
                    planConfig.setCustomerId(saasParkFireInspectPlan.getCustomerId());
                    planConfig.setTaskPlanId(planTask.getId());
                    planConfig.setInspectStatus("0");
                    planConfig.setTaskPlanType("2");
                    planConfig.setCreateOrgUser(contextUser.getOrgUserId());
                    planConfig.setSort(sort);
                    taskConfigList.add(planConfig);
                    sort++;
                }
            }
        }
        // 保存任务巡检点
        planConfigService.saveBatch(taskConfigList);
        return Boolean.TRUE;
    }

    private void setTaskOutTimeValue(SaasParkFireInspectPlanTask planTask, FireInspectPlanSubmitReqDTO reqDTO) {
        // 过期时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(planTask.getTaskEndTime());
        if ("1".equals(reqDTO.getTaskEndNotifyType())) {
            // 增加分钟
            calendar.add(Calendar.MINUTE, reqDTO.getTaskEndNotify());
        }
        if ("2".equals(reqDTO.getTaskEndNotifyType())) {
            // 增加小时
            calendar.add(Calendar.HOUR, reqDTO.getTaskEndNotify());
        }
        if ("3".equals(reqDTO.getTaskEndNotifyType())) {
            // 增加天
            calendar.add(Calendar.DATE, reqDTO.getTaskEndNotify());
        }
        planTask.setTaskOutTime(calendar.getTime());

    }

    private void setTaskNotifyTimeValue(SaasParkFireInspectPlanTask planTask, FireInspectPlanSubmitReqDTO reqDTO) {
        // 过期时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(planTask.getTaskStartTime());
        if ("1".equals(reqDTO.getTaskEndNotifyType())) {
            // 减少分钟
            calendar.add(Calendar.MINUTE, -reqDTO.getTaskEndNotify());
        } else
        if ("2".equals(reqDTO.getTaskEndNotifyType())) {
            // 减少小时
            calendar.add(Calendar.HOUR, -reqDTO.getTaskEndNotify());
        } else
        if ("3".equals(reqDTO.getTaskEndNotifyType())) {
            // 减少天
            calendar.add(Calendar.DATE, -reqDTO.getTaskEndNotify());
        } else {
            throw new ServiceException("任务通知选择时间周期不正确");
        }
        planTask.setTaskNotifyTime(calendar.getTime());

    }

    private void validRepeat(SaasParkFireInspectPlan saasParkFireInspectPlan) {
        int count = count(new LambdaQueryWrapper<SaasParkFireInspectPlan>()
                .eq(SaasParkFireInspectPlan::getInspectPlanName, saasParkFireInspectPlan.getInspectPlanName())
                .eq(Objects.nonNull(saasParkFireInspectPlan.getProjectId()), SaasParkFireInspectPlan::getProjectId, saasParkFireInspectPlan.getProjectId())
                .notIn(Objects.nonNull(saasParkFireInspectPlan.getId()), BaseEntity::getId, saasParkFireInspectPlan.getId()));
        if (count > 0) {
            throw new ServiceException("巡检计划名称不能重复");
        }
    }

    private void verifySubmitParam(FireInspectPlanSubmitReqDTO reqDTO) {
        // 巡检配置不能为空
        if (CollUtil.isEmpty(reqDTO.getPlanConfigDTOList())) {
            throw new ServiceException("计划排班任务数不能为空");
        }
        // 时间段不能为空
        if (CollUtil.isEmpty(reqDTO.getPlanTimePeriodValueDTOList())) {
            throw new ServiceException("时间段不能为空");
        }
        // 任务计划不能为空
        if (CollUtil.isEmpty(reqDTO.getContentDataList())) {
            throw new ServiceException("计划排班任务数不能为空");
        }
        // 不是按天，需要必传 计划规则周期值不能为空
        if (!StrUtil.equals(reqDTO.getPlanRuleCycle(), "1")) {
            if (CollUtil.isEmpty(reqDTO.getPlanRuleCycleValue())) {
                throw new ServiceException("计划规则周期值不能为空");
            }
        }
        // 巡检人类型为成员
        List<Long> orgUserIdList;
        switch (reqDTO.getInspectPeopleType()) {
            case "1":
                if (CollUtil.isEmpty(reqDTO.getOrgUserIdList())) {
                    throw new ServiceException("巡检人不能为空");
                }
                break;
            // 巡检人类型为部门
            case "2":
                if (Objects.isNull(reqDTO.getDeptRoleId())) {
                    throw new ServiceException("请选择部门");
                }
                // 获取部门下的成员列表
                List<UserDept> userDeptList = iUserDeptClient.listByDeptId(reqDTO.getDeptRoleId()).getData();
                if (CollUtil.isEmpty(userDeptList)) {
                    throw new ServiceException("该部门下没有成员");
                }
                orgUserIdList = userDeptList.stream().map(UserDept::getOrgUserId).collect(Collectors.toList());
                reqDTO.setOrgUserIdList(orgUserIdList);
                break;
            // 巡检人类型为部门
            case "3":
                if (Objects.isNull(reqDTO.getDeptRoleId())) {
                    throw new ServiceException("请选择角色");
                }
                // 获取部门下的成员列表
                List<NestOrgRoleBinding> orgRoleBindingList = iOrgRoleClient.listByOrgRoleId(reqDTO.getDeptRoleId()).getData();
                if (CollUtil.isEmpty(orgRoleBindingList)) {
                    throw new ServiceException("该部门下没有成员");
                }
                orgUserIdList = orgRoleBindingList.stream().map(NestOrgRoleBinding::getOrgUserId).collect(Collectors.toList());
                reqDTO.setOrgUserIdList(orgUserIdList);
                break;
            default:
                throw new ServiceException("请选择正确的巡检人类型");
        }
        // 判断任务要求，是否通知
        if ("1".equals(reqDTO.getTaskStartNotifyDemand())) {
            if (Objects.isNull(reqDTO.getTaskStartNotify()) && StrUtil.isBlank(reqDTO.getTaskStartNotifyType())) {
                throw new ServiceException("开启任务通知时，任务通知时间内容不能为空");
            }
        }
        if ("1".equals(reqDTO.getTaskEndNotifyDemand())) {
            if (Objects.isNull(reqDTO.getTaskEndNotify()) && StrUtil.isBlank(reqDTO.getTaskEndNotifyType())) {
                throw new ServiceException("开启任务过期时，任务过期时间内容不能为空");
            }
        }
    }

    @Override
    public FireInspectPlanTaskTableVO createPlanTaskInfo(FireInspectPlanSubmitReqDTO reqDTO) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Objects.isNull(contextUser)) {
            throw new ServiceException("用户不存在");
        }
        List<Long> orgUserIdList;
        // 巡检人类型为成员
        switch (reqDTO.getInspectPeopleType()) {
            case "1":
                if (CollUtil.isEmpty(reqDTO.getOrgUserIdList())) {
                    throw new ServiceException("巡检人不能为空");
                }
                orgUserIdList = reqDTO.getOrgUserIdList();
                break;
            // 巡检人类型为部门
            case "2":
                if (Objects.isNull(reqDTO.getDeptRoleId())) {
                    throw new ServiceException("请选择部门");
                }
                // 获取部门下的成员列表
                List<UserDept> userDeptList = iUserDeptClient.listByDeptId(reqDTO.getDeptRoleId()).getData();
                if (CollUtil.isEmpty(userDeptList)) {
                    throw new ServiceException("该部门下没有成员");
                }
                orgUserIdList = userDeptList.stream().map(UserDept::getOrgUserId).collect(Collectors.toList());
                break;
            // 巡检人类型为角色
            case "3":
                if (Objects.isNull(reqDTO.getDeptRoleId())) {
                    throw new ServiceException("请选择角色");
                }
                // 获取部门下的成员列表
                List<NestOrgRoleBinding> orgRoleBindingList = iOrgRoleClient.listByOrgRoleId(reqDTO.getDeptRoleId()).getData();
                if (CollUtil.isEmpty(orgRoleBindingList)) {
                    throw new ServiceException("该角色下没有成员");
                }
                orgUserIdList = orgRoleBindingList.stream().map(NestOrgRoleBinding::getOrgUserId).collect(Collectors.toList());
                break;
            default:
                throw new ServiceException("请选择正确的巡检人类型");
        }
        // 获取选中的组织成员列表
        List<NestOrgUser> orgUserList = iOrgUserClient.findOrgUserListByIds(orgUserIdList).getData();
        Map<Long, String> orgUserMap = orgUserList.stream().collect(Collectors.toMap(BaseEntity::getId, NestOrgUser::getName));

        FireInspectPlanTaskTableVO taskTableVO = new FireInspectPlanTaskTableVO();
        // 获取开始日期和结束日期
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String planStartDate = simpleDateFormat.format(reqDTO.getPlanStartDate());
        String planEndDate = simpleDateFormat.format(reqDTO.getPlanEndDate());
        LocalDate date1 = LocalDate.parse(planStartDate);
        LocalDate date2 = LocalDate.parse(planEndDate);
        // 计算相隔天数,需要加1
        List<LocalDate> dateList = getDatesBetween(date1, date2);
        // 表头日期数据
        List<String> headDateList = new ArrayList<>();
        // 表头第一个值写死时段
        headDateList.add("任务时间段");
        for (LocalDate localDate : dateList) {
            String dateValue = localDate.toString();
            //判断计划规则选择周期类型（1：天，2：周，3：月，4：年，5：自定义）
            switch (reqDTO.getPlanRuleCycle()) {
                case "1":
                    headDateList.add(dateValue);
                    break;
                case "2":
                    // 判断周几
                    String weekValue = WeekEnum.getDescByCode(localDate.getDayOfWeek().name());
                    if (reqDTO.getPlanRuleCycleValue().contains(weekValue)) {
                        headDateList.add(dateValue);
                    }
                    break;
                case "3":
                    // 判断日期是几号
                    String monthValue = String.valueOf(localDate.getDayOfMonth());
                    if (reqDTO.getPlanRuleCycleValue().contains(monthValue)) {
                        headDateList.add(dateValue);
                    }
                    break;
            }
        }
        taskTableVO.setHeadDateList(headDateList);
        // 生成表内容
        List<List<FireInspectPlanTaskTableVO.OrgUserData>> contentDataList = new ArrayList<>();
        // 时间段列表
        List<PlanTimePeriodValueDTO> planTimePeriodValueDTOList = reqDTO.getPlanTimePeriodValueDTOList();
        int count = 0;// 用来取余 算获取哪个人员
        // 分配方式1：每人全时段
        switch (reqDTO.getDistributionMode()) {
            case "1": {
                // 增加上第一个值，并循环每个人全时段
                for (PlanTimePeriodValueDTO valueDTO : planTimePeriodValueDTOList) {
                    // 人员排版计划
                    List<FireInspectPlanTaskTableVO.OrgUserData> orgUserDataList = new ArrayList<>();
                    // 返回第一个值为时间段值
                    FireInspectPlanTaskTableVO.OrgUserData timePeriodData = new FireInspectPlanTaskTableVO.OrgUserData();
                    if (valueDTO.getTimePeriod() > 0) {
                        timePeriodData.setOrgUserNames(valueDTO.getPlanStartTimePeriod() + "~" + valueDTO.getPlanEndTimePeriod() + "+" + valueDTO.getTimePeriod() + "天");
                    } else {
                        timePeriodData.setOrgUserNames(valueDTO.getPlanStartTimePeriod() + "~" + valueDTO.getPlanEndTimePeriod());
                    }
                    timePeriodData.setPeriodValueDTO(valueDTO);
                    orgUserDataList.add(0, timePeriodData);
                    for (String headData : headDateList) {
                        if (headData.equals("任务时间段")) {
                            continue;
                        }
                        FireInspectPlanTaskTableVO.OrgUserData orgUserData = new FireInspectPlanTaskTableVO.OrgUserData();
                        // 计算排班到第几个成员
                        int temp = count % orgUserIdList.size();
                        // 成员列表
                        List<Long> orgUserIds = new ArrayList<>();
                        orgUserIds.add(orgUserIdList.get(temp));
                        orgUserData.setOrgUserIdList(orgUserIds);
                        orgUserData.setOrgUserNames(orgUserMap.get(orgUserIdList.get(temp)));
                        orgUserData.setTaskDate(headData);
                        orgUserDataList.add(orgUserData);
                        count++;
                    }
                    // 添加每一行
                    contentDataList.add(orgUserDataList);
                }
                break;
            }
            // 分配方式 2：每人1时段
            case "2": {
                // 人员排版计划
                List<FireInspectPlanTaskTableVO.OrgUserData> orgUserDataList = new ArrayList<>();
                // 循环日期
                for (String headData : headDateList) {
                    if (headData.equals("任务时间段")) {
                        continue;
                    }
                    // 循环每个时段
                    for (PlanTimePeriodValueDTO valueDTO : planTimePeriodValueDTOList) {
                        FireInspectPlanTaskTableVO.OrgUserData orgUserData = new FireInspectPlanTaskTableVO.OrgUserData();
                        // 计算排班到第几个成员
                        int temp = count % orgUserIdList.size();
                        // 成员列表
                        List<Long> orgUserIds = new ArrayList<>();
                        orgUserIds.add(orgUserIdList.get(temp));
                        orgUserData.setOrgUserIdList(orgUserIds);
                        orgUserData.setOrgUserNames(orgUserMap.get(orgUserIdList.get(temp)));
                        orgUserData.setTaskDate(headData);
                        if (valueDTO.getTimePeriod() > 0) {
                            orgUserData.setPeriodValue(valueDTO.getPlanStartTimePeriod() + "~" + valueDTO.getPlanEndTimePeriod() + "+" + valueDTO.getTimePeriod() + "天");
                        } else {
                            orgUserData.setPeriodValue(valueDTO.getPlanStartTimePeriod() + "~" + valueDTO.getPlanEndTimePeriod());
                        }
                        orgUserDataList.add(orgUserData);
                        count++;
                    }
                }
                // 根据时间段进行分组
                Map<String, List<FireInspectPlanTaskTableVO.OrgUserData>> listMap = orgUserDataList.stream()
                        .collect(Collectors.groupingBy(FireInspectPlanTaskTableVO.OrgUserData::getPeriodValue, // 分组条件
                                LinkedHashMap::new, // 使用LinkedHashMap保持顺序
                                Collectors.toList()));
                // 增加上第一个值，并循环每个人全时段
                for (PlanTimePeriodValueDTO valueDTO : planTimePeriodValueDTOList) {
                    // 返回第一个值为时间段值
                    FireInspectPlanTaskTableVO.OrgUserData timePeriodData = new FireInspectPlanTaskTableVO.OrgUserData();
                    if (valueDTO.getTimePeriod() > 0) {
                        timePeriodData.setOrgUserNames(valueDTO.getPlanStartTimePeriod() + "~" + valueDTO.getPlanEndTimePeriod() + "+" + valueDTO.getTimePeriod() + "天");
                    } else {
                        timePeriodData.setOrgUserNames(valueDTO.getPlanStartTimePeriod() + "~" + valueDTO.getPlanEndTimePeriod());
                    }
                    timePeriodData.setPeriodValueDTO(valueDTO);
                    listMap.get(timePeriodData.getOrgUserNames()).add(0, timePeriodData);
                    // 添加每一行内容
                    contentDataList.add(listMap.get(timePeriodData.getOrgUserNames()));
                }
                break;
            }
            // 分配方式 3：全员分配
            case ("3"): {
                // 每一行增加上第一个值
                for (PlanTimePeriodValueDTO valueDTO : planTimePeriodValueDTOList) {
                    // 人员排版计划
                    List<FireInspectPlanTaskTableVO.OrgUserData> orgUserDataList = new ArrayList<>();
                    // 返回第一个值为时间段值
                    FireInspectPlanTaskTableVO.OrgUserData timePeriodData = new FireInspectPlanTaskTableVO.OrgUserData();
                    if (valueDTO.getTimePeriod() > 0) {
                        timePeriodData.setOrgUserNames(valueDTO.getPlanStartTimePeriod() + "~" + valueDTO.getPlanEndTimePeriod() + "+" + valueDTO.getTimePeriod() + "天");
                    } else {
                        timePeriodData.setOrgUserNames(valueDTO.getPlanStartTimePeriod() + "~" + valueDTO.getPlanEndTimePeriod());
                    }
                    timePeriodData.setPeriodValueDTO(valueDTO);
                    orgUserDataList.add(0, timePeriodData);
                    for (String headData : headDateList) {
                        if (headData.equals("任务时间段")) {
                            continue;
                        }
                        FireInspectPlanTaskTableVO.OrgUserData orgUserData = new FireInspectPlanTaskTableVO.OrgUserData();
                        // 成员列表
                        orgUserData.setOrgUserIdList(orgUserIdList);
                        // 获取成员名称
                        List<String> orgUserNameList = new ArrayList<>();
                        for (Long orgUserId : orgUserIdList) {
                            orgUserNameList.add(orgUserMap.get(orgUserId));
                        }
                        orgUserData.setOrgUserNames(CollUtil.join(orgUserNameList, ","));
                        orgUserData.setTaskDate(headData);
                        orgUserDataList.add(orgUserData);
                    }
                    // 添加每一行
                    contentDataList.add(orgUserDataList);
                }
                break;
            }
        }
        taskTableVO.setContentDataList(contentDataList);
        return taskTableVO;
    }

    @Override
    public void exportPlanTaskInfo(Long planId, HttpServletResponse response) {
        FireInspectPlanTaskTableVO taskTableVO = getPlanTaskTable(planId);
        // 动态创建表头名称
        List<List<String>> headList = new ArrayList<>();
        // 设置表头信息
        setExportHead(headList, taskTableVO);
        // 组装数据
        List<List<String>> dataList = new ArrayList<>();
        // 设置内容信息
        setExportContent(dataList, taskTableVO);
        try {
            NoModelWriteDataDTO dataDTO = new NoModelWriteDataDTO();
            dataDTO.setFileName("计划任务表");
            dataDTO.setHeadMap(headList);
            dataDTO.setDataList(dataList);
            ExcelUtils.noModelTempWriteExport(dataDTO, response);
        } catch (Exception e) {
            log.error("Exception :", e);
        }

    }

    private void setExportContent(List<List<String>> dataList, FireInspectPlanTaskTableVO taskTableVO) {
        if (CollUtil.isEmpty(taskTableVO.getContentDataList())) {
            throw new ServiceException("表头数据不存在");
        }
        for (List<FireInspectPlanTaskTableVO.OrgUserData> orgUserDataList : taskTableVO.getContentDataList()) {
            List<String> list = new ArrayList<>();
            for (FireInspectPlanTaskTableVO.OrgUserData orgUserData : orgUserDataList) {
                list.add(orgUserData.getOrgUserNames());
            }
            dataList.add(list);
        }
    }

    private void setExportHead(List<List<String>> headList, FireInspectPlanTaskTableVO taskTableVO) {
        if (CollUtil.isEmpty(taskTableVO.getHeadDateList())) {
            throw new ServiceException("表头数据不存在");
        }
        for (String headName : taskTableVO.getHeadDateList()) {
            List<String> list = new ArrayList<>();
            list.add(headName);
            headList.add(list);
        }
    }

    private static List<LocalDate> getDatesBetween(LocalDate startDate, LocalDate endDate) {
        List<LocalDate> dateList = new ArrayList<>();
        LocalDate currentDate = startDate;

        // 使用循环逐日生成日期并添加到列表
        while (!currentDate.isAfter(endDate)) {
            dateList.add(currentDate);
            currentDate = currentDate.plusDays(1);
        }

        return dateList;
    }
}
