package cn.wisenergy.service.impl;

import cn.wisenergy.common.utils.DateUtil;
import cn.wisenergy.common.utils.DateUtils;
import cn.wisenergy.common.utils.exception.BASE_RESP_CODE_ENUM;
import cn.wisenergy.common.utils.exception.BaseCustomException;
import cn.wisenergy.mapper.*;
import cn.wisenergy.model.app.*;
import cn.wisenergy.model.dto.*;
import cn.wisenergy.model.enums.LevelEnum;
import cn.wisenergy.model.enums.LevelRankEnum;
import cn.wisenergy.model.enums.OrderChangeEnum;
import cn.wisenergy.model.enums.StatusEnum;
import cn.wisenergy.model.vo.OrderChangeManagerVo;
import cn.wisenergy.model.vo.OrderChangeVo;
import cn.wisenergy.service.*;
import cn.wisenergy.service.utils.UserRoleLevelUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

import static java.util.Collections.sort;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author chenqi
 * @since 2021-01-19
 */
@Service
@Slf4j
public class WorkTimeOrderServiceImpl implements WorkTimeOrderService {

    @Autowired
    private WorkUserService workUserService;

    @Autowired
    private WorkUserMapper workUserMapper;

    @Autowired
    private WorkOrderChangeService workOrderChangeService;

    @Autowired
    private WorkTypeService workTypeService;

    @Autowired
    private WorkProjectService workProjectService;

    @Autowired
    private WorkProjectMapper workProjectMapper;

    @Autowired
    private WorkTimeOrderMapper workTimeOrderMapper;

    @Autowired
    private WorkDeptService workDeptService;

    @Autowired
    private WorkSubmitAdoptService workSubmitAdoptService;

    @Autowired
    private WorkHolidayService workHolidayService;

    @Autowired
    private WorkCollectService workCollectService;

    @Autowired
    private WorkCentreService workCentreService;

    @Autowired
    private WorkUserProjectService workUserProjectService;

    @Autowired
    private StatisticsService statisticsService;

    @Autowired
    private WorkOrderChangeMapper workOrderChangeMapper;

    @Autowired
    private WorkCollectMapper workCollectMapper;

    @Autowired
    private WorkLeaveMapper workLeaveMapper;

    @Autowired
    private WorkHolidayMapper workHolidayMapper;

    // 长请假最大天数
    private final Integer LONG_LEAVE_DAYS = 142;


    // 工单状态

    private final Integer COMPLETED = StatusEnum.COMPLETED.getCode();
    private final Integer APPROVED = StatusEnum.APPROVED.getCode();
    private final Integer REJECTED = StatusEnum.REJECTED.getCode();
    private final Integer RE_SUBMIT = StatusEnum.RE_SUBMIT.getCode();
    private final Integer AUTOMATIC_AUDIT = StatusEnum.AUTOMATIC_AUDIT.getCode();

    /**
     * 功能; 获取某日填报情况
     *
     * @param userId  用户id
     * @param workDay 某日
     * @return 工单集合
     */
    @Override

    public List<WorkTimeOrder> getByDay(Integer userId, Date workDay) {
        log.info("WorkTimeOrderServiceImpl[]getByDay[]input.param.userId:{},workDay:{}" + userId, workDay);

        if (null == userId || null == workDay) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        List<WorkTimeOrder> workTimeOrders = workTimeOrderMapper.getByDay(userId, workDay);
        if (CollectionUtils.isEmpty(workTimeOrders)) {
            return null;
        }

        return workTimeOrders;
    }

    /**
     * 功能：获取某日填报小计
     *
     * @param userId  用户id
     * @param workDay 某日
     * @return 填报小计
     */
    @Override
    public SubtotalDto getSubtotalReport(Integer userId, Date workDay) {
        log.info("WorkTimeOrderServiceImpl[]getSubtotalReport[]input.param.userId:{},workDay:{}" + userId, workDay);
        if (null == userId || null == workDay) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }

        List<WorkTimeOrder> workTimeOrders = getByDay(userId, workDay);
        if (CollectionUtils.isEmpty(workTimeOrders)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_ORDER_INFO_IS_NULL);
        }
        SubtotalDto subtotalDto = new SubtotalDto();
        // 今日总工时
        int totalTime = 0;
        // 被驳回原因
        StringBuilder reason = new StringBuilder();
        subtotalDto.setUserId(userId);
        subtotalDto.setWorkDay(workDay);
        List<Integer> typeIds = workTypeService.getIdByReviewer(1);

        for (WorkTimeOrder wto : workTimeOrders) {
            totalTime += wto.getWorkTime();
            if (null != wto.getReason() && REJECTED.equals(wto.getStatus()) && "".equals(reason.toString())) {
                if (!CollectionUtils.isEmpty(typeIds)) {
                    if (typeIds.contains(wto.getType())) {
                        reason.append(workProjectService.getById(wto.getProjectId()).getProjectName()).append(":").append(wto.getReason()).append(";");
                    }
                    if (!typeIds.contains(wto.getType())) {
                        List<WorkType> workTypes = workTypeService.getAll(null);
                        if (!CollectionUtils.isEmpty(workTimeOrders)) {
                            for (WorkType value : workTypes) {
                                if (value.getId().equals(wto.getType())) {
                                    reason.append(value.getName()).append(":").append(wto.getReason()).append(";");
                                }
                            }
                        }
                    }
                }

            }
        }

        subtotalDto.setReason(reason.toString());
        subtotalDto.setTotalTime(totalTime);
        return subtotalDto;
    }

    /**
     * 功能; 获取某日填报信息
     *
     * @param userId  用户id
     * @param workDay 工作日
     * @return dto
     */
    @Override
    public List<WorkTimeOrder> getByDayToDto(Integer userId, Date workDay) {
        log.info("WorkTimeOrderServiceImpl[]getByDayToDto[]input.param.userId:{},workDay:{}" + userId, workDay);
        List<WorkTimeOrder> workTimeOrders = getByDay(userId, workDay);
        if (CollectionUtils.isEmpty(workTimeOrders)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_ORDER_INFO_IS_NULL);
        }
        return workTimeOrders;
    }


    /**
     * 功能：添加工单
     *
     * @param createWorkOrderDto dto
     * @return dto
     */
    @Transactional
    @Override
    public List<WorkTimeOrderDto> addOrder(CreateWorkOrderDto createWorkOrderDto) {
        log.info("WorkTimeOderServiceImpl[]addTest[]input.param.creatWorkOrderDto" + createWorkOrderDto);
        if (null == createWorkOrderDto || CollectionUtils.isEmpty(createWorkOrderDto.getWorkTimeOrders())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_ORDER_INFO_IS_NULL);
        }
        WorkUser user = workUserService.getById(createWorkOrderDto.getWorkTimeOrders().get(0).getUserId());
        List<WorkTimeOrderDto> workTimeOrders = createWorkOrderDto.getWorkTimeOrders();
        Date date = new Date();
        WorkSubmitAdopt workSubmitAdopt = workSubmitAdoptService.getById(1);
        Integer submitTime = workSubmitAdopt.getSubmitTime();

        // 1.判断是否重复填报
        isRepeat(workTimeOrders);
        // 2.每天工时累加不得超过八小时
        timeNotEight(0, workTimeOrders);
        int totalTime = 0;
        List<WorkTimeOrder> addList = new ArrayList<>(8);
        List<WorkType> workTypes = workTypeService.getAll(null);
        List<Integer> notDeleteOrder = new ArrayList<>(8);

        // 3.验证填报类型项目是否已经结项
        orderIsEnd(workTimeOrders, workTypes);
        for (WorkTimeOrderDto dto : workTimeOrders) {
            // 4.判断工单是否合法
            isEmpty(dto);

            // 5.设置状态
            if (null == dto.getStatus() || 0 == dto.getStatus()) {
                dto.setStatus(COMPLETED);
            }
            if (null != dto.getStatus() && REJECTED.equals(dto.getStatus())) {
                dto.setStatus(RE_SUBMIT);
            }
            // 6.是否加班
            dto.setIsOvertime(0);
            if (workHolidayService.isHoliday(dto.getWorkDay())) {
                dto.setIsOvertime(1);
            }
            // 7.是否已经审批
            WorkTimeOrder workTimeOrder = new WorkTimeOrder();
            workTimeOrder.setDeptId(user.getDeptId());
            BeanUtils.copyProperties(dto, workTimeOrder);
            totalTime += dto.getWorkTime();
            if (null != dto.getWorkId()) {
                WorkTimeOrder workTimeOrder1 = workTimeOrderMapper.selectById(dto.getWorkId());
                if (2 == workTimeOrder1.getStatus() || 5 == workTimeOrder1.getStatus()) {
                    if (!dto.getStatus().equals(workTimeOrder1.getStatus())) {
                        throw new BaseCustomException(BASE_RESP_CODE_ENUM.ORDER_EXAMINE);
                    }
                    notDeleteOrder.add(workTimeOrder1.getWorkId());
                    continue;
                } else {
                    WorkTimeOrder order = new WorkTimeOrder();
                    BeanUtils.copyProperties(dto, order);
                    if (workTimeOrder1.equals(order)) {
                        notDeleteOrder.add(workTimeOrder1.getWorkId());
                        continue;
                    }
                }
            }
            BeanUtils.copyProperties(workTimeOrder, dto);
            addList.add(workTimeOrder);
        }
        // 8.判断是否超时
        WorkCollect workCollect = workCollectService.getByUserIdAndWorkDay(workTimeOrders.get(0).getUserId(), workTimeOrders.get(0).getWorkDay());
        for (WorkTimeOrder dto : addList) {
            if (null != workCollect && null != workCollect.getRejectTime()) {
                Date rejectTime1 = workCollect.getRejectTime();
                Date rejectTime = DateUtil.convertStrToDate(DateUtil.convertDateToStr(rejectTime1, "yyyy-MM-dd"), "yyyy-MM-dd");
                if (DateUtil.isThanDay(rejectTime, date, submitTime)) {
                    throw new BaseCustomException("627", "超过" + submitTime + "天的不能填报");
                }
            }
            // 4、默认设置超过系统默认3天（包括驳回3天）未填报的工时将不能填报
            if (!REJECTED.equals(dto.getStatus()) && !RE_SUBMIT.equals(dto.getStatus())) {
                if (DateUtil.isThanDay(dto.getWorkDay(), date, submitTime)) {
                    throw new BaseCustomException("627", "超过" + submitTime + "天的不能填报");
                }
            }
        }

        // 9.删除数据库还没有审批的工单，添加填报没有审批的工单
        UpdateWrapper<WorkTimeOrder> wrapper = new UpdateWrapper<>();
        wrapper.eq("user_id", workTimeOrders.get(0).getUserId());
        wrapper.eq("work_day", workTimeOrders.get(0).getWorkDay());
        wrapper.notIn(!CollectionUtils.isEmpty(notDeleteOrder), "work_id", notDeleteOrder);
        workTimeOrderMapper.delete(wrapper);
        if (!CollectionUtils.isEmpty(addList)) {
            for (WorkTimeOrder workTimeOrder : addList) {
                workTimeOrderMapper.save(workTimeOrder);
            }
        }
        // 10.更新collect表
        int status = statusYes(workTimeOrders.get(0).getUserId(), workTimeOrders.get(0).getWorkDay());

        if (null == workCollect) {
            workCollect = new WorkCollect();
            BeanUtils.copyProperties(workTimeOrders.get(0), workCollect);
            workCollect.setTotalTime(totalTime);
            workCollect.setStatus(status);
            workCollectService.insertCollect(workCollect);
        }
        if (null != workCollect) {
            workCollect = new WorkCollect();
            BeanUtils.copyProperties(workTimeOrders.get(0), workCollect);
            workCollect.setTotalTime(totalTime);
            workCollect.setStatus(status);
            workCollectService.update(workCollect);
        }

        return workTimeOrders;
    }


    private void orderIsEnd(List<WorkTimeOrderDto> workTimeOrders, List<WorkType> workTypes) {
        if (!CollectionUtils.isEmpty(workTimeOrders) || !CollectionUtils.isEmpty(workTypes)) {
            List<WorkProject> projectsByIds = workProjectMapper.getProjectsByIds(null, 0);
            if (!CollectionUtils.isEmpty(projectsByIds)) {
                for (WorkTimeOrderDto workTimeOrder : workTimeOrders) {
                    if (StatusEnum.APPROVED.getCode().equals(workTimeOrder.getStatus()) || StatusEnum.AUTOMATIC_AUDIT.getCode().equals(workTimeOrder.getStatus())) {
                        continue;
                    }
                    if (workTimeOrder.getType().equals(1) || workTimeOrder.getType().equals(2)) {
                        for (WorkProject projectsById : projectsByIds) {
                            if (projectsById.getId().equals(workTimeOrder.getProjectId())) {

                                throw new BaseCustomException("666", projectsById.getProjectName() + "已经结束，请重新选择填报");
                            }
                        }
                    } else {
                        for (WorkType workType : workTypes) {
                            if (workType.getStatus().equals(0)) {
                                if (workType.getId().equals(workTimeOrder.getType())) {
                                    throw new BaseCustomException("667", workType.getName() + "已经结束，请重新选择填报");
                                }
                            }
                        }
                    }

                }
            }
        }
    }

    // 判断填写工时单是否重复
    private void isRepeat(List<?> ts) {
        List<WorkTimeOrder> list = new ArrayList<>();
        if (CollectionUtils.isEmpty(ts)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        ts.forEach(t ->{
            if (t instanceof WorkTimeOrder) {
                list.add((WorkTimeOrder) t);
            }else{
                WorkTimeOrderDto workTimeOrderDto = (WorkTimeOrderDto) t;
                WorkTimeOrder workTimeOrder = new WorkTimeOrder();
                BeanUtils.copyProperties(workTimeOrderDto,workTimeOrder);
                list.add(workTimeOrder);
            }
           });
        List<Integer> typeIds = workTypeService.getIdByReviewer(1);
        int size = list.size();
        for (int i = 0; i < size; i++) {
            for (int j = i + 1; j < size; j++) {
                if (!CollectionUtils.isEmpty(typeIds)) {
                    if (typeIds.contains(list.get(i).getType())) {
                        if (list.get(j).getType().equals(list.get(i).getType())) {
                            if (null == list.get(i).getProjectId() || null == list.get(j).getProjectId()) {
                                throw new BaseCustomException(BASE_RESP_CODE_ENUM.NO_JOIN_EVERY_PROJECT_PLASE_JION);
                            } else if (list.get(i).getProjectId().equals(list.get(j).getProjectId())) {
                                throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_ORDER_ALREADY_COMMIT);
                            }
                        }
                    } else if (list.get(i).getType().equals(list.get(j).getType())) {
                        throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_ORDER_ALREADY_COMMIT);
                    }
                }
            }
        }
    }

    /**
     * 功能：获取待审批数据
     *
     * @param userId    用户id
     * @param projectId 项目id
     * @param type      项目类型
     * @param status    状态
     * @return 自定义dto
     */
    @Override
    public PageInfo<WorkTimeOrderDto> getExamine(Integer userId, Integer projectId, Integer type, Integer page, Integer pageSize, List<Integer> status) {
        log.info("WorkOrderServiceImpl[]getExamine[]input.param.userId:{},projectId:{},type:{},page:{},size:{},status:{}" + userId, projectId, type, page, pageSize, status);
        // 判断当前用户是否是管理员
        if (!UserRoleLevelUtils.isManagerLevel(userId, LevelEnum.EXAMINE.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.USER_NOT_LEVEL);
        }
        WorkUser user = workUserService.getById(userId);

        // PC端
        return pageExamine(user, projectId, type, page, pageSize, status);
    }

    /**
     * 功能：获取小程序待审批
     *
     * @param userId    用户id
     * @param projectId 项目Id
     * @param type      类型
     * @return dto
     */
    @Override
    public List<AppletsPendApprovalDto> getExamineApplets(Integer userId, Integer projectId, Integer type) {
        log.info("WorkOrderServiceImpl[]getExamineApplets[]input.param.userId:{},projectId:{},type:{}" + userId, projectId, type);
        if (!UserRoleLevelUtils.isManagerLevel(userId, LevelEnum.EXAMINE.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.USER_NOT_LEVEL);
        }
        WorkUser user = workUserService.getById(userId);
        if (null == projectId && null == type) {
            return null;
        }
        if (UserRoleLevelUtils.isManagerLevel(userId, LevelEnum.EXAMINE.getLevelName())) {
            QueryWrapper<WorkTimeOrder> wrapper = new QueryWrapper<>();
            wrapper.in("status", COMPLETED, RE_SUBMIT);
            wrapper.eq(type != null, "type", type);
            wrapper.eq(type != null, "dept_id", user.getDeptId());
            wrapper.eq(projectId != null, "project_id", projectId);
            wrapper.orderByDesc("work_day");
            List<WorkTimeOrder> workTimeOrders = workTimeOrderMapper.selectList(wrapper);
            if (CollectionUtils.isEmpty(workTimeOrders)) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_ORDER_END);
            }
            return getDto(workTimeOrders);
        }
        throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_ORDER_END);
    }

    // 封装可填报的数据
    private List<AppletsPendApprovalDto> getDto(List<WorkTimeOrder> workTimeOrders) {
        List<AppletsPendApprovalDto> appletsPendApprovalDtos = new ArrayList<>(10);
        Date date = workTimeOrders.get(0).getWorkDay();
        AppletsPendApprovalDto dto = new AppletsPendApprovalDto();
        dto.setWorkDay(date);
        appletsPendApprovalDtos.add(dto);
        WorkUser user = workUserService.getById(workTimeOrders.get(0).getUserId());
        for (WorkTimeOrder workTimeOrder : workTimeOrders) {
            if (date.compareTo(workTimeOrder.getWorkDay()) != 0) {
                date = workTimeOrder.getWorkDay();
                AppletsPendApprovalDto dto2 = new AppletsPendApprovalDto();
                dto2.setWorkDay(workTimeOrder.getWorkDay());
                appletsPendApprovalDtos.add(dto2);
            }
        }
        for (WorkTimeOrder workTimeOrder : workTimeOrders) {
            System.out.println(workTimeOrder);
        }
        List<Integer> typeIds = workTypeService.getIdByReviewer(1);
        List<WorkType> workTypes = workTypeService.getAll(null);
        for (AppletsPendApprovalDto approvalDto : appletsPendApprovalDtos) {
            List<WorkTimeOrderDto> workTimeOrderList = new ArrayList<>();
            for (WorkTimeOrder workTimeOrder : workTimeOrders) {
                if (approvalDto.getWorkDay().compareTo(workTimeOrder.getWorkDay()) == 0) {
                    WorkTimeOrderDto workTimeOrderDto = new WorkTimeOrderDto();
                    BeanUtils.copyProperties(workTimeOrder, workTimeOrderDto);
                    Integer deptManagerId = workDeptService.getById(user.getDeptId()).getDeptManagerId();
                    if (null != deptManagerId) {
                        workTimeOrderDto.setManagerName(workUserService.getById(deptManagerId).getName());
                    }
                    workTimeOrderDto.setUserName(workUserService.getById(workTimeOrderDto.getUserId()).getName());
                    if (!CollectionUtils.isEmpty(typeIds)) {
                        if (typeIds.contains(workTimeOrder.getType())) {
                            workTimeOrderDto.setProjectName(workProjectService.getById(workTimeOrderDto.getProjectId()).getProjectName());
                            workTimeOrderDto.setManagerName(workUserService.getById(workProjectService.getById(workTimeOrderDto.getProjectId()).getManagerId()).getName());
                        }
                    }
                    workTimeOrderDto.setTypeName(getTypeName(workTimeOrderDto.getType(), workTypes));
                    workTimeOrderList.add(workTimeOrderDto);
                }
            }
            approvalDto.setWorkTimeOrderDto(workTimeOrderList);
        }
        return appletsPendApprovalDtos;
    }

    /**
     * 功能：批量审批
     *
     * @param reviewerId 审批人
     * @param ids        工单
     * @return 是否成功
     */
    @Transactional
    @Override
    public Boolean examineByIds(Integer reviewerId, List<Integer> ids) {
        log.info("WorkOrderServiceImpl[]examineByIds[]input.param.ids:" + ids);
        if (CollectionUtils.isEmpty(ids)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        if (!UserRoleLevelUtils.isManagerLevel(reviewerId, LevelEnum.EXAMINE.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.USER_NOT_LEVEL);
        }
        int i = workTimeOrderMapper.updateByIds(reviewerId, ids);
        if (i == 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.UPDATE_DATA_FAIL);
        }

        List<WorkTimeOrder> workTimeOrders = workTimeOrderMapper.selectBatchIds(ids);
        if (ids.size() != workTimeOrders.size()) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.HAVE_ORDER_DELETE);
        }
        // 更新collect表
        workCollectService.updateByWorkTimeOrder(workTimeOrders);

        return true;
    }

    /**
     * 功能： 驳回
     *
     * @param reviewerId 审核人id
     * @param id         工单id
     * @param reason     驳回理由
     * @return 是否成功
     */
    @Transactional
    @Override
    public Boolean rejectById(Integer reviewerId, Integer id, String reason) {
        log.info("WorkOrderServiceImpl[]rejectById[]input.param.reviewerId:{},id:{},reason:{}" + reviewerId, id, reason);
        if (null == reviewerId || null == id || StringUtils.isBlank(reason)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        // 判断当前用户是否有权限
        if (!UserRoleLevelUtils.isManagerLevel(reviewerId, LevelEnum.EXAMINE.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.USER_NOT_LEVEL);
        }
        // 修改工单状态
        int i = workTimeOrderMapper.updateStatusById(reviewerId, id, reason);
        if (i == 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.UPDATE_DATA_FAIL);
        }
        WorkTimeOrder workTimeOrder = workTimeOrderMapper.selectById(id);
        Integer userId = workTimeOrder.getUserId();
        Date workDay = workTimeOrder.getWorkDay();
        WorkCollect workCollect = workCollectService.getByUserIdAndWorkDay(userId, workDay);
        if (null == workCollect) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_ORDER_INFO_IS_NULL);
        }
        workCollect.setStatus(REJECTED);
        return workCollectService.update(workCollect);
    }

    /**
     * 功能：查询驳回未提交的
     *
     * @param userId 用户id
     * @return dto
     */
    @Transactional
    @Override
    public List<WorkTimeOrderDto> rejectNotSubmit(Integer userId) {
        log.info("WorkOrderServiceImpl[]rejectNotSubmit[]input.param.id:{}" + userId);
        if (!UserRoleLevelUtils.isManagerLevel(userId, LevelEnum.EXAMINE.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.USER_NOT_LEVEL);
        }
        Date startDate;
        Date endDate;
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        WorkSubmitAdopt submitAdopt = workSubmitAdoptService.getById(1);
        Integer orderChange = submitAdopt.getOrderChange();
        calendar.add(Calendar.DAY_OF_MONTH, -orderChange);
        startDate = DateUtil.getFirstDayOfMonth(calendar.getTime());
        endDate = DateUtil.getLastDayByMonth2(calendar.getTime());
        QueryWrapper<WorkTimeOrder> wrapper = new QueryWrapper<>();
        wrapper.ge("work_day", startDate);
        wrapper.le("work_day", endDate);
        wrapper.eq("reviewer_id", userId);
        wrapper.eq("status", REJECTED);
        wrapper.orderByDesc("work_day");
        List<WorkTimeOrder> workTimeOrders = workTimeOrderMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(workTimeOrders)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.NO_WORK_ORDERS_HAVE_BEEN_REJECTED);
        }
        return wtoToWtod(workTimeOrders);
    }

    /**
     * 功能：获取用户参与的项目
     *
     * @param userId 用户id
     * @return dto
     */
    @Override
    public ProjectsDto getProjectDto(Integer userId) {
        log.info("WorkOrderServiceImpl[]getProjectDto[]input.param.userId:{}" + userId);
        System.out.println(userId);
        if (null == userId) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        ProjectsDto projectsDto = new ProjectsDto();
        WorkUser user = workUserService.getById(userId);
        // 逻辑删后的东西
        List<WorkType> workTypeList = workTypeService.getByIsStatus(1, 1);
        projectsDto.setWorkTypeList(workTypeList);
        // 1.获取可填报的类型
        List<WorkType> workTypes = workTypeService.getAll(1);
        if (!CollectionUtils.isEmpty(workTypes)) {
            projectsDto.setWorkTypes(workTypes);
        }
        // 2.获取可填报的项目
        projectsDto.setProjectInfoDto(getProjectInfoDto(userId));
        // 3.获取可审批的项目
        List<ProjectManagerDto> projectManagerDto = getProjectManagerDto(user, workTypes);
        if (!CollectionUtils.isEmpty(projectManagerDto)) {
            projectsDto.setProjectManagerDto(projectManagerDto);
            return projectsDto;
        }
        return projectsDto;
    }

    private List<ProjectManagerDto> getProjectManagerDto(WorkUser user, List<WorkType> workTypes) {
        List<UserRoleLevelDto> roleUserLevel = UserRoleLevelUtils.getRoleUserLevel(user.getId());

        if (CollectionUtils.isEmpty(roleUserLevel)) {
            return null;
        }
        List<ProjectManagerDto> projectManagerDtos = new ArrayList<>();
        for (UserRoleLevelDto userRoleLevelDto : roleUserLevel) {
            // 如果有审批权限
            if (LevelEnum.EXAMINE.getLevelName().equals(userRoleLevelDto.getLevelName())) {
                List<ProjectDto> projectDtos = workProjectService.getByManagerId(user.getId(), 1);
                if (LevelRankEnum.PROJECT_LEVEL.getRank().equals(userRoleLevelDto.getRank())) {
                    if (!CollectionUtils.isEmpty(projectDtos)) {
                        QueryWrapper<WorkTimeOrder> wrapper = new QueryWrapper<>();
                        List<Integer> projectIds = new ArrayList<>();
                        for (ProjectDto projectDto : projectDtos) {
                            projectIds.add(projectDto.getId());
                        }
                        wrapper.in("project_id", projectIds);
                        wrapper.in("status", COMPLETED, RE_SUBMIT);
                        List<WorkTimeOrder> timeOrders = workTimeOrderMapper.selectList(wrapper);
                        ProjectManagerDto projectManagerDto;
                        for (ProjectDto projectDto : projectDtos) {
                            projectManagerDto = new ProjectManagerDto();
                            Integer pendingApprovalTimes = 0;
                            for (WorkTimeOrder timeOrder : timeOrders) {
                                if (timeOrder.getProjectId().equals(projectDto.getId())) {
                                    pendingApprovalTimes++;
                                }
                            }
                            projectManagerDto.setPendingApprovalTimes(pendingApprovalTimes);
                            BeanUtils.copyProperties(projectDto, projectManagerDto);
                            projectManagerDtos.add(projectManagerDto);
                        }
                    }
                }

                if (LevelRankEnum.DEPARTMENT_LEVEL.getRank().equals(userRoleLevelDto.getRank())) {
                    List<WorkType> workTypeServiceAll = workTypeService.getAll(null);
                    if (!CollectionUtils.isEmpty(workTypeServiceAll)) {
                        List<WorkType> managerTypes = new ArrayList<>();
                        Set<Integer> set = new TreeSet<>();
                        workTypes.forEach(type -> {
                            if (3 == type.getReviewer()) {
                                set.add(type.getId());
                                managerTypes.add(type);
                            }
                        });
                        QueryWrapper<WorkTimeOrder> wrapper = new QueryWrapper<>();
                        wrapper.in("type", set);
                        wrapper.eq("dept_id", user.getDeptId());
                        wrapper.in("status", COMPLETED, RE_SUBMIT);
                        List<WorkTimeOrder> timeOrders = workTimeOrderMapper.selectList(wrapper);
                        ProjectManagerDto projectManagerDto1;
                        for (WorkType workType : managerTypes) {
                            projectManagerDto1 = new ProjectManagerDto();
                            Integer pendingApprovalTimes = 0;
                            for (WorkTimeOrder timeOrder : timeOrders) {
                                if (workType.getId()
                                        .equals(timeOrder.getType())) {
                                    pendingApprovalTimes++;
                                }
                            }
                            projectManagerDto1.setPendingApprovalTimes(pendingApprovalTimes);
                            projectManagerDto1.setType(workType.getId());
                            projectManagerDto1.setTypeName(workType.getName());
                            projectManagerDtos.add(projectManagerDto1);
                        }
                    }
                }
            }
        }
        sort(projectManagerDtos);
        return projectManagerDtos;

    }

    // 获取可以填报的数据
    private List<ProjectInfoDto> getProjectInfoDto(Integer userId) {
        // 获取该用户参与的项目
        List<Integer> projectIds = workUserProjectService.getProjectIdByUserId(userId);

        // 1.获取当前用户的部门管理
        Integer deptId = workUserService.getById(userId).getDeptId();
        Integer deptManagerId = workDeptService.getById(deptId).getDeptManagerId();
        String deptManagerName = null;
        if (null != deptManagerId) {
            deptManagerName = workUserService.getById(workDeptService.getById(deptId).getDeptManagerId()).getName();
        }
        // 2.获取可填报的类型
        List<ProjectInfoDto> projectList = new ArrayList<>();
        // 3.获取正在进行中的项目/商机
        List<WorkProject> projects = workProjectService.getNameByIds(projectIds, 1);

        ProjectInfoDto projectInfoDto;
        List<WorkType> workTypes = workTypeService.getByIsStatus(1, 1);
        if (!CollectionUtils.isEmpty(workTypes)) {
            for (WorkType value : workTypes) {
                projectInfoDto = new ProjectInfoDto().setType(value.getId()).setTypeName(value.getName()).setDeptManagerName(deptManagerName);
                if (1 == value.getReviewer()) {
                    if (!CollectionUtils.isEmpty(projects)) {
                        List<ProjectDto> projectDtos = new ArrayList<>();
                        for (WorkProject project : projects) {
                            if (project.getType().equals(value.getId())) {
                                ProjectDto projectDto = new ProjectDto();
                                BeanUtils.copyProperties(project, projectDto);
                                projectDto.setManagerName(workUserService.getById(project.getManagerId()).getName());
                                projectDtos.add(projectDto);
                            }
                        }
                        projectInfoDto.setProjectDto(projectDtos);
                    }

                }
                projectList.add(projectInfoDto);
            }

        }
        return projectList;
    }


    // workTimeOrder TO WorkTimeOrderDto
    @Override
    public List<WorkTimeOrderDto> wtoToWtod(List<WorkTimeOrder> workTimeOrders) {
        List<WorkTimeOrderDto> dtos = new ArrayList<>();
        WorkUser user = workUserService.getById(workTimeOrders.get(0).getUserId());
        List<Integer> typeIds = workTypeService.getIdByReviewer(1);
        List<WorkType> workTypes = workTypeService.getAll(null);
        for (WorkTimeOrder workTimeOrder : workTimeOrders) {
            WorkTimeOrderDto dto = new WorkTimeOrderDto();
            BeanUtils.copyProperties(workTimeOrder, dto);
            dto.setUserName(workUserService.getById(workTimeOrder.getUserId()).getName());
            Integer deptManagerId = workDeptService.getById(user.getDeptId()).getDeptManagerId();
            if (null != deptManagerId) {
                dto.setManagerName(workUserService.getById(deptManagerId).getName());
            }
            if (!CollectionUtils.isEmpty(typeIds)) {
                if (typeIds.contains(workTimeOrder.getType())) {
                    dto.setProjectName(workProjectService.getById(workTimeOrder.getProjectId()).getProjectName());
                    dto.setManagerName(getManagerNameByOrder(workTimeOrder));
                }
            }
            dto.setTypeName(getTypeName(dto.getType(), workTypes));
            dtos.add(dto);
        }
        return dtos;
    }


    // 判断工单是否合法
    private void isEmpty(WorkTimeOrderDto dto) {
        int size = 0;
        int range = 2;
        if (null == dto.getType()) {
            size++;
        }
        if (null == dto.getWorkTime() || 0 == dto.getWorkTime()) {
            size++;
        }
        if (1 == dto.getType() || range == dto.getType()) {
            if (null == dto.getProjectId()) {
                size++;
            }
        }
        if (null == dto.getDes() || "".equals(dto.getDes())) {
            size++;
        }
        if (size >= range) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INCOMPLETE_WORK_ORDER_INFORMATION);
        }


        if (null == dto.getWorkTime() || 0 == dto.getWorkTime()) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.TIME_NOT_IS_NULL);
        }
        if (null == dto.getWorkDay()) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORKDAY_NOT_NULL);
        }
        if (null == dto.getType() || 0 == dto.getType()) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.PROJECT_NOT_NULL);
        }
        if (thanDate(dto.getWorkDay())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_TIME_OVER_NOW_DAY);
        }
        if (1 == dto.getType() || 2 == dto.getType()) {
            if (null == dto.getProjectId()) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.NO_JOIN_EVERY_PROJECT_PLASE_JION);
            }

        }
        List<WorkType> workTypes = workTypeService.getAll(null);
        if (!CollectionUtils.isEmpty(workTypes)) {
            for (WorkType value : workTypes) {
                if (value.getReviewer() == 2) {
                    if (dto.getType().equals(value.getId())) {
                        return;
                    }
                }
            }
        }
        if (null == dto.getDes() || "".equals(dto.getDes())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.DES_NOT_NULL);
        }
    }

    //3.每天工时累加不得超过八小时
    private int timeNotEight(int totalTime, List<?> ts) {
        List<WorkTimeOrder> list = new ArrayList<>(8);
        if (!CollectionUtils.isEmpty(ts)) {
            ts.forEach(t -> {
                if (t instanceof WorkTimeOrder) {
                    list.add((WorkTimeOrder) t);
                }else{
                    WorkTimeOrder workTimeOrder = new WorkTimeOrder();
                    WorkTimeOrderDto workTimeOrderDto = (WorkTimeOrderDto) t;
                    BeanUtils.copyProperties(workTimeOrderDto,workTimeOrder);
                    list.add(workTimeOrder);
                }
                });
        }
        if (!CollectionUtils.isEmpty(list)) {
            for (WorkTimeOrder workOrder : list) {
                totalTime = totalTime + workOrder.getWorkTime();
            }
        }
        if (totalTime > 8) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_TIME_NOT_OVER_EIGHT);
        }
        return totalTime;
    }

    //判断填报是否超过今天
    private boolean thanDate(Date date) {
        Date date1 = new Date();
        int i;
        i = date1.compareTo(date);
        return -1 == i;
    }


    // 审批分页
    private PageInfo<WorkTimeOrderDto> pageExamine(WorkUser user, Integer projectId, Integer type, Integer page, Integer pageSize, List<Integer> status) {
        log.info("WorkOrderServiceImpl[]pageExamine[]input.param.user:{},projectId:{},type:{},page:{},pageSize:{},status:{}" + user, projectId, type, page, pageSize, status);
        page = page == null ? 1 : page;
        pageSize = pageSize == null ? 10 : pageSize;
        List<WorkType> workTypes = workTypeService.getAll(1);
        List<Integer> projectIds = new ArrayList<>();
        List<Integer> types = new ArrayList<>();

        if (null == projectId && null == type) {
            List<ProjectManagerDto> projectManagerDto = getProjectManagerDto(user, workTypes);
            if (!CollectionUtils.isEmpty(projectManagerDto)) {
                projectManagerDto.forEach(project -> {
                    if (null != project.getId()) {
                        projectIds.add(project.getId());
                    } else {
                        types.add(project.getType());
                    }
                });
            } else {
                projectIds.add(-1);
                types.add(-1);
            }
        } else {
            if (null != projectId) {
                projectIds.add(projectId);
            }
            if (null != type) {
                types.add(type);
            }
        }
        Page<WorkTimeOrderDto> pageHelper = null;
        List<WorkTimeOrder> workTimeOrders = null;
        if (UserRoleLevelUtils.isManagerLevel(user.getId(), LevelEnum.EXAMINE.getLevelName())) {
            pageHelper = PageHelper.startPage(page, pageSize);
            Integer deptId = user.getDeptId();
            workTimeOrders = workTimeOrderMapper.queryByPage(status, projectIds, types, deptId);
        }
        List<WorkTimeOrderDto> workTimeOrderDtos = new ArrayList<>();
        List<WorkUser> workUsers = workUserMapper.selectList(new QueryWrapper<>());
        List<WorkProject> workProjects = workProjectMapper.selectList(new QueryWrapper<>());
        for (WorkTimeOrder workTimeOrder : workTimeOrders) {
            WorkTimeOrderDto workTimeOrderDto = new WorkTimeOrderDto();
            BeanUtils.copyProperties(workTimeOrder, workTimeOrderDto);
            for (WorkUser workUser : workUsers) {
                if (workTimeOrderDto.getUserId().equals(workUser.getId())) {
                    workTimeOrderDto.setUserName(workUser.getName());
                }
            }
            for (WorkProject workProject : workProjects) {
                if (null != workTimeOrderDto.getProjectId() && workTimeOrderDto.getProjectId().equals(workProject.getId())) {
                    workTimeOrderDto.setProjectName(workProject.getProjectName());
                }
            }
            workTimeOrderDto.setTypeName(getTypeName(workTimeOrderDto.getType(), workTypes));
            workTimeOrderDtos.add(workTimeOrderDto);
        }
        PageInfo<WorkTimeOrderDto> pageInfo = pageHelper.toPageInfo();
        pageInfo.setList(workTimeOrderDtos);
        return pageInfo;
    }


    // 根据工单获取管理员
    private String getManagerNameByOrder(WorkTimeOrder wto) {
        List<Integer> typeIds = workTypeService.getIdByReviewer(1);
        if (!CollectionUtils.isEmpty(typeIds)) {
            if (typeIds.contains(wto.getType())) {
                WorkProject workProject = workProjectService.getById(wto.getProjectId());
                return workProject != null ? workUserService.getById(workProject.getManagerId()).getName() : "";
            } else {
                Integer deptManagerId = workDeptService.getById(wto.getDeptId()).getDeptManagerId();
                if (null != deptManagerId) {
                    return workUserService.getById(deptManagerId).getName();
                }
            }
        }
        return null;
    }


    private String getTypeName(Integer type, List<WorkType> workTypes) {
        if (!CollectionUtils.isEmpty(workTypes)) {
            for (WorkType value : workTypes) {
                if (value.getId().equals(type)) {
                    return value.getName();
                }
            }
        }
        return null;
    }

    /**
     * 判断当天是否全部审批通过
     */
    @Override
    public int statusYes(Integer userId, Date workDay) {
        int status = COMPLETED;
        int size = 0;
        List<WorkTimeOrder> workTimeOrderDtos = workTimeOrderMapper.getByDay(userId, workDay);
        for (WorkTimeOrder dto : workTimeOrderDtos) {
            if (APPROVED.equals(dto.getStatus()) || AUTOMATIC_AUDIT.equals(dto.getStatus())) {
                size++;
            }
            if (REJECTED.equals(dto.getStatus())) {
                status = REJECTED;
            }
        }
        if (size == workTimeOrderDtos.size()) {
            status = APPROVED;
        }
        return status;
    }

    /**
     * 获取本部门 填报缺失信息
     *
     * @param userId 管理员id
     * @return 填报缺失信息
     */
    @Override
    public NotWorkSubmitOrderDto getDeptNotOrderInfo(Integer userId) {
        log.info("WorkOrderServiceImpl[]getDeptNotOrderInfo[]input.param.userId" + userId);
        if (null == userId) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        WorkUser user = workUserService.getById(userId);
        List<Integer> ranks = UserRoleLevelUtils.getRankByUserAndLevelName(userId, LevelEnum.USER_STATISTICS.getLevelName());
        if (CollectionUtils.isEmpty(ranks)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }
        Integer rankMax = null;
        for (Integer rank : ranks) {
            rankMax = rankMax == null ? rank : rank > rankMax ? rank : rankMax;
        }
        if (rankMax == null) {
            return null;
        }
        NotWorkSubmitOrderDto notWorkSubmitOrderDto = new NotWorkSubmitOrderDto();
        List<DeptUserCollectDto> deptNotOrderInfo = new ArrayList<>();
        List<Integer> deptIds = new ArrayList<>();
        WorkSubmitAdopt adopt = workSubmitAdoptService.getById(1);
        Integer submitTime = adopt.getSubmitTime();

        Date date = new Date();
        Date startDate;
        Date endDate;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -submitTime);
        if (DateUtil.isYearAndMonthEqual(date, calendar.getTime())) {
            startDate = DateUtil.getFirstDayOfMonth(date);
            endDate = date;
        } else {
            startDate = DateUtil.getFirstDayOfMonth(calendar.getTime());
            endDate = DateUtil.getLastDayByMonth2(calendar.getTime());
        }
        System.out.println(DateUtils.dateToShortString(startDate));
        System.out.println(DateUtils.dateToShortString(endDate));
        boolean flag = DateUtil.isYearAndMonthEqual(date, date);
        List<Date> workDays = statisticsService.currentMonthWorkDays(date, flag);

        List<DeptUserDto> deptUserDtos = new ArrayList<>();

        notWorkSubmitOrderDto.setDate(date);
        if (LevelRankEnum.CENTRAL_LEVEL.getRank().equals(rankMax)) {
            List<WorkDept> deptByCentreManager = workCentreService.getDeptByCentreManager(user);
            for (WorkDept workDept : deptByCentreManager) {
                DeptUserDto deptUserDto = new DeptUserDto();
                deptUserDto.setDeptId(workDept.getId());
                deptUserDto.setDeptName(workDept.getDeptName());
                deptUserDtos.add(deptUserDto);
            }
            if (CollectionUtils.isEmpty(deptByCentreManager)) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.DEPT_NOT_FOUND);
            }
            deptByCentreManager.forEach(dept -> deptIds.add(dept.getId()));
            deptNotOrderInfo = workTimeOrderMapper.getDeptNotOrderInfo(userId, deptIds, startDate, endDate);

        }
        if (LevelRankEnum.DEPARTMENT_LEVEL.getRank().equals(rankMax)) {
            deptIds.add(user.getDeptId());
            deptNotOrderInfo = workTimeOrderMapper.getDeptNotOrderInfo(userId, deptIds, startDate, endDate);
            DeptUserDto deptUserDto = new DeptUserDto();
            if (!CollectionUtils.isEmpty(deptNotOrderInfo)) {
                deptUserDto.setDeptId(deptNotOrderInfo.get(0).getDeptId());
                deptUserDto.setDeptName(deptNotOrderInfo.get(0).getDeptName());
                deptUserDtos.add(deptUserDto);
            } else {
                deptUserDto.setDeptId(user.getDeptId());
                deptUserDto.setDeptName(workDeptService.getById(user.getDeptId()).getDeptName());
                deptUserDtos.add(deptUserDto);
            }
        }
        if (!CollectionUtils.isEmpty(deptUserDtos) && !CollectionUtils.isEmpty(deptNotOrderInfo)) {
            for (DeptUserDto deptUserDto : deptUserDtos) {
                List<UserDto> userDtos = new ArrayList<>();
                for (DeptUserCollectDto deptUserCollectDto : deptNotOrderInfo) {
                    UserDto userDto = new UserDto();
                    List<Date> workDays1 = new ArrayList<>(workDays);
                    Date createDate = DateUtils.bigDateToShortDate(deptUserCollectDto.getCreateTime());
                    workDays1.removeIf(date1 -> date1.compareTo(createDate) < 0);
                    userDto.setId(deptUserCollectDto.getUserId());
                    userDto.setName(deptUserCollectDto.getUserName());
                    workDays1.removeAll(deptUserCollectDto.getWorkDay());
                    userDto.setNotWorkDays(workDays1.size());
                    if (deptUserCollectDto.getDeptId().equals(deptUserDto.getDeptId())) {
                        userDtos.add(userDto);

                    }
                }
                deptUserDto.setUserDtos(userDtos);
            }
        }
        if (!CollectionUtils.isEmpty(deptUserDtos)) {
            for (DeptUserDto deptUserDto : deptUserDtos) {
                if (!CollectionUtils.isEmpty(deptUserDto.getUserDtos())) {
                    deptUserDto.getUserDtos().removeIf(userDto -> 0 == userDto.getNotWorkDays());
                }
            }
        }
        notWorkSubmitOrderDto.setDeptUserDtos(deptUserDtos);
        return notWorkSubmitOrderDto;
    }

    /**
     * 工单变更管理分页
     *
     * @param vo 条件
     * @return 分页
     */
    @Override
    public PageInfo<OrderChangePageDto> getOrderChangePage(OrderChangeManagerVo vo) {
        log.info("WorkOrderServiceImpl[]getOrderChangePage[]input.param.OrderChangeManagerVo" + vo);
        if (null == vo || null == vo.getUserId()) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }

        if (!UserRoleLevelUtils.isManagerLevel(vo.getUserId(), LevelEnum.WORKORDER_CHANGEMANAGEMENT.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }
        List<DeptOfProjectAndOrderType> projectAndOrderTypes = workProjectService.getProjectAndOrderTypeAndDept(vo.getUserId()).getProjectAndOrderTypes();
        if (CollectionUtils.isEmpty(projectAndOrderTypes)) {
            return null;
        }
        OrderChangeLogMapperDto mapperDto = workOrderChangeService.getMapperOrderChangeMapperDto(null, projectAndOrderTypes, vo);
        System.out.println("mapperDto = " + mapperDto);
        vo.setPage(null == vo.getPage() ? 1 : vo.getPage());
        vo.setPageSize(null == vo.getPageSize() ? 10 : vo.getPageSize());
        PageHelper.startPage(vo.getPage(), vo.getPageSize());
        List<OrderChangePageDto> orderChangePage = workTimeOrderMapper.getOrderChangePage(mapperDto);
        if (!CollectionUtils.isEmpty(orderChangePage)) {
            for (OrderChangePageDto orderChangePageDto : orderChangePage) {
                for (StatusEnum value : StatusEnum.values()) {
                    if (orderChangePageDto.getStatus().equals(value.getCode())) {
                        orderChangePageDto.setStatusName(value.getMsg());
                    }
                }
            }
        }
        PageInfo<OrderChangePageDto> pageInfo = new PageInfo<>(orderChangePage);
        pageInfo.setList(orderChangePage);
        return pageInfo;
    }

    @Transactional
    @Override
    public Boolean createOrderChange(OrderChangeVo vo) {
        log.info("WorkTimeOrderServiceImpl[]createOrderChange[]input.param.OrderChangeVo:{}" + vo);
        // 1.判断参数是否为空
        OrderChangeVoIsNull(vo, false);

        // 2.是否超过8小时
        int totalTime = vo.getWorkTime();
        List<WorkTimeOrder> workTimeOrders = getByDay(vo.getUserId(), vo.getWorkDay());
        List<WorkTimeOrder> workTimeOrderList = new ArrayList<>(8);
        if (!CollectionUtils.isEmpty(workTimeOrders)) {
            workTimeOrderList.addAll(workTimeOrders);
        }
        totalTime = timeNotEight(totalTime, workTimeOrders);
        // 3.判断工时类型和项目是否重复
        WorkTimeOrder workTimeOrder = new WorkTimeOrder();
        BeanUtils.copyProperties(vo, workTimeOrder);
        workTimeOrderList.add(workTimeOrder);
        isRepeat(workTimeOrderList);
        // 4.插入workTimeOrder表
        WorkTimeOrder timeOrder = getOrderChangeWorkTimeOrder(vo, workTimeOrder);
        int saveTimeOrderRow = workTimeOrderMapper.save(timeOrder);
        if (saveTimeOrderRow == 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INSERT_DATA_IS_FAIL);
        }
        // 5.插入workCollect表
        insertWorkCollect(vo, totalTime, CollectionUtils.isEmpty(workTimeOrders), false, null);

        // 增加记录
        addWorkOrderChange(OrderChangeEnum.CREATE.getContent(), vo);
        return true;
    }

    @Transactional
    @Override
    public Boolean updateOrderChange(OrderChangeVo vo) {
        log.info("WorkTimeOrderServiceImpl[]updateOrderChange[]input.param.OrderChangeVo:{}" + vo);
        // 1.判断参数是否为空
        OrderChangeVoIsNull(vo, true);
        // 2.获取原工单，并验证修改内容是否与原工单一致
        WorkTimeOrder workTimeOrderOld = workTimeOrderMapper.selectById(vo.getWorkId());
        List<WorkTimeOrder> workTimeOrders = getByDay(workTimeOrderOld.getUserId(), vo.getWorkDay());
        if (vo.getWorkDay().equals(workTimeOrderOld.getWorkDay()) && vo.getWorkTime().equals(workTimeOrderOld.getWorkTime()) && vo.getDes().equals(workTimeOrderOld.getDes())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.theNewContent_IsEqual_ToTheOriginal_Content);
        }
        vo.setUserId(workTimeOrderOld.getUserId());
        vo.setProjectId(workTimeOrderOld.getProjectId());
        vo.setType(workTimeOrderOld.getType());
        // 3.判断是否超过8小时
        int totalTime = vo.getWorkTime();
        if (!CollectionUtils.isEmpty(workTimeOrders)) {
            workTimeOrders.removeIf(workTimeOrder -> workTimeOrder.getWorkId().equals(vo.getWorkId()));
        }
        totalTime = timeNotEight(totalTime, workTimeOrders);
        // 4.判断工时类型是否重复
        List<WorkTimeOrder> workTimeOrderList = new ArrayList<>(8);
        if (!CollectionUtils.isEmpty(workTimeOrders)) {
            workTimeOrderList.addAll(workTimeOrders);
        }
        WorkTimeOrder workTimeOrder = new WorkTimeOrder();
        BeanUtils.copyProperties(vo, workTimeOrder);
        workTimeOrderList.add(workTimeOrder);
        isRepeat(workTimeOrderList);

        System.out.println("4444444444");
        // 5.修改workTimeOrder工单
        WorkTimeOrder timeOrder = getOrderChangeWorkTimeOrder(vo, workTimeOrder);
        int i = workTimeOrderMapper.updateById(timeOrder);
        if (i == 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INSERT_DATA_IS_FAIL);
        }
        // 判断是否是同一天
        if (vo.getWorkDay().compareTo(workTimeOrderOld.getWorkDay()) == 0) {
            insertWorkCollect(vo, totalTime, false, false, null);
        } else {
            // 6.修改或插入workCollect表
            insertWorkCollect(vo, totalTime, CollectionUtils.isEmpty(workTimeOrders), false, null);
            // 7.修改或删除原workCollect表
            List<WorkTimeOrder> workTimeOrdersOld = getByDay(workTimeOrderOld.getUserId(), workTimeOrderOld.getWorkDay());
            System.out.println(workTimeOrdersOld);
            if (!CollectionUtils.isEmpty(workTimeOrdersOld)) {
                totalTime = 0;
                for (WorkTimeOrder order : workTimeOrdersOld) {
                    totalTime += order.getWorkTime();
                }
            }
            insertWorkCollect(vo, totalTime, false, CollectionUtils.isEmpty(workTimeOrdersOld), workTimeOrderOld);
        }

        // 增加记录
        addWorkOrderChange(OrderChangeEnum.UPDATE.getContent(), vo);
        return true;
    }

    @Transactional
    @Override
    public Boolean deleteOrderChange(Integer workId, Integer operator,String changeReason) {
        log.info("WorkTimeOrderServiceImpl[]deleteOrderChange[]input.param.workId:{},operator:{},changeReason:{}" + workId, operator,changeReason);
        if (null == workId || null == operator || StringUtils.isBlank(changeReason)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        if (!UserRoleLevelUtils.isManagerLevel(operator, LevelEnum.WORKORDER_CHANGEMANAGEMENT.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }
        // 查询原工单
        WorkTimeOrder workTimeOrder = workTimeOrderMapper.selectById(workId);
        // 原工单当天的
        List<WorkTimeOrder> workTimeOrders = getByDay(workTimeOrder.getUserId(), workTimeOrder.getWorkDay());
        workTimeOrders.removeIf(workTimeOrder1 -> workTimeOrder1.getWorkId().equals(workTimeOrder.getWorkId()));

        OrderChangeVo vo = new OrderChangeVo();
        BeanUtils.copyProperties(workTimeOrder,vo );
        vo.setOperatorId(operator);

        // 删除记录
        workTimeOrderMapper.deleteById(workId);

        if (!CollectionUtils.isEmpty(workTimeOrders)) {
            int i = statusYes(workTimeOrder.getUserId(), workTimeOrder.getWorkDay());
            int totalTime = 0;
            for (WorkTimeOrder timeOrder : workTimeOrders) {
                totalTime += timeOrder.getWorkTime();
            }
            WorkCollect workCollect = new WorkCollect();
            workCollect.setUserId(workTimeOrder.getUserId()).setWorkDay(workTimeOrder.getWorkDay()).setStatus(i).setTotalTime(totalTime);

            Boolean update = workCollectService.update(workCollect);
            if (!update) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.UPDATE_DATA_FAIL);
            }
        }else{
            Boolean aBoolean = workCollectService.deleteByUserIdAndWorkDay(workTimeOrder.getUserId(), workTimeOrder.getWorkDay());
            if (!aBoolean) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.FAILEDTO_DELETE_DATA);
            }
        }
        vo.setChangeReason(changeReason);
        // 增加记录
        addWorkOrderChange(OrderChangeEnum.DELETE.getContent(), vo);

        return true;
    }

    @Transactional
    @Override
    public Boolean takeALongLeave(TakeALongLeaveParam takeALongLeaveParam) {
        log.info("WorkTimeOrderServiceImpl[]takeALongLeave[]input.param{}takeALongLeaveParam" + takeALongLeaveParam.toString());
        Integer userId = takeALongLeaveParam.getUserId();
        Integer type = takeALongLeaveParam.getTypeId();
        String startDate = takeALongLeaveParam.getStartDate();
        String endDate = takeALongLeaveParam.getEndDate();
        String des = takeALongLeaveParam.getDes();
        if (userId == null || type == null || StringUtils.isEmpty(startDate) || StringUtils.isEmpty(endDate)||  StringUtils.isEmpty(des)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }


        // 开始日期和结束日期是否在可填报时间段
        WorkSubmitAdopt submitAdopt = workSubmitAdoptService.getById(1);
        // 限制填报天数
        Integer submitTime = submitAdopt.getSubmitTime();
        // 开始结束日期转为date
        Date start = DateUtil.convertStrToDate(startDate, "yyyy-MM-dd");
        Date end = DateUtil.convertStrToDate(endDate, "yyyy-MM-dd");

        // 开始时间不能大于结束时间
        if (start.compareTo(end) == 1) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.LONG_LEAVE_START_NOT__GREATER_END);
        }

        // 当前日期
        Date today = DateUtil.getStartOfDay(new Date());

        Date add = DateUtil.add(start, Calendar.DAY_OF_MONTH, submitTime);

        Date lastDayByMonth = DateUtil.add(start, Calendar.DAY_OF_YEAR, LONG_LEAVE_DAYS);
        if (add.compareTo(today) < 1 || lastDayByMonth.compareTo(end) == -1) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.LONG_LEAVE_DATE_ERROR);
        }


        // 所有类型名称
        List<WorkType> workTypes = workTypeService.getAll(0);
        // 用户填报的类型
        String typeName = getTypeName(type, workTypes);
        if (!"请假".equals(typeName) && !"调休".equals(typeName)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.LONG_LEAVE_TYPE_ERROR);
        }
        // 用户信息
        WorkUser user = workUserService.getById(userId);

        // 请假时间段内不能够存在已填报工单
        int i = workTimeOrderMapper.countByWorkDay(userId, startDate, endDate);
        if (i != 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_DAY_IS_REPEAT);
        }

        // 去除掉日期段内的节假日
        // 选择日期段内的所有日期集合
        List<Date> datesBetweenTwoDate = DateUtil.getDatesBetweenTwoDate(start, end);
        // 从日期集合中除去周末
        for (int j = 0; j < datesBetweenTwoDate.size(); j++) {
            int week = DateUtil.getWeek(datesBetweenTwoDate.get(j));
            if (week == 7 || week == 1) {
                datesBetweenTwoDate.remove(j);
                j--;
            }
        }

        // 在填报日期内的节假日和补班日
        List<WorkHoliday> holidays = workHolidayMapper.getByDate(start, end);
        if (!CollectionUtils.isEmpty(holidays)) {
            for (WorkHoliday holiday : holidays) {
                List<Date> holidayList = DateUtil.getDatesBetweenTwoDate(holiday.getDayStart(), holiday.getDayEnd());
                // 为1就是节假日,否则补班
                if (holiday.getDayType().equals(1)) {
                    datesBetweenTwoDate.removeAll(holidayList);
                }else {
                    datesBetweenTwoDate.addAll(holidayList);
                }
            }
        }

        // 所填报日期中没有工作日
        if (datesBetweenTwoDate.size() == 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.LONG_LEAVE_DATE_NOT_ONLY_HOLIDAY);
        }
//        for (int i1 = 0; i1 < datesBetweenTwoDate.size(); i1++) {
//            // 为节假日,从日期集合中删除
//            if (workHolidayService.isHoliday(datesBetweenTwoDate.get(i1))) {
//                datesBetweenTwoDate.remove(i1);
//                i1--;
//            }
//            if (datesBetweenTwoDate.size() == 0) {
//                throw new BaseCustomException(BASE_RESP_CODE_ENUM.LONG_LEAVE_DATE_NOT_ONLY_HOLIDAY);
//            }
//        }

        // 需要插入的工单集合
        List<WorkTimeOrder> workTimeOrders = new ArrayList<>();
        // 插入工单汇总
        List<WorkCollect> workCollects = new ArrayList<>();
        for (Date date : datesBetweenTwoDate) {
            // 工单信息
            WorkTimeOrder workTimeOrder = new WorkTimeOrder();
            workTimeOrder.setUserId(userId);
            workTimeOrder.setType(type);
            workTimeOrder.setDeptId(user.getDeptId());
            workTimeOrder.setWorkDay(date);
            workTimeOrder.setIsOvertime(0);
            workTimeOrder.setStatus(StatusEnum.COMPLETED.getCode());
            workTimeOrder.setDes(des);
            workTimeOrder.setWorkTime(8);
            workTimeOrder.setCreateTime(new Date());
            workTimeOrder.setModifyTime(new Date());
            workTimeOrders.add(workTimeOrder);

            // 汇总信息
            WorkCollect workCollect = new WorkCollect();
            workCollect.setUserId(userId);
            workCollect.setStatus(StatusEnum.COMPLETED.getCode());
            workCollect.setTotalTime(8);
            workCollect.setWorkDay(date);
            workCollect.setCreateTime(new Date());
            workCollect.setModifyTime(new Date());
            workCollects.add(workCollect);
        }

        // 添加work_time_order记录
        int workOrderCount = workTimeOrderMapper.addManyLeaveOrder(workTimeOrders);

        // 添加work_collect记录
        int workCollectCount = workCollectMapper.addManyLeaveCollect(workCollects);

        // 添加work_leave记录
        WorkLeave workLeave = new WorkLeave();
        BeanUtils.copyProperties(takeALongLeaveParam, workLeave);
        workLeave.setCreateTime(DateUtil.getTime(new Date(),"yyyy-MM-dd-HH-mm-ss"));
        workLeave.setModifyTime(DateUtil.getTime(new Date(),"yyyy-MM-dd-HH-mm-ss"));
        int workLeaveCount = workLeaveMapper.insert(workLeave);

        if (workOrderCount == 0 || workCollectCount == 0 || workLeaveCount == 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.UPDATE_DATA_FAIL);
        }
        return true;
    }

    @Override
    public List<LeaveResult> getUserLongLeaveInfo(Integer userId) {
        log.info("WorkTimeOrderServiceImpl[]getUserLongLeaveInfo[]input.param{}userId" + userId);
        if (userId == null) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        // 所有填报类型信息
        List<WorkType> workTypes = workTypeService.getAll(null);
        // 数据库中存储的信息
        List<WorkLeave> listByUserId = workLeaveMapper.getListByUserId(userId);
        // 返回信息
        List<LeaveResult> leaveResultList = new ArrayList<>();
        for (WorkLeave workLeave : listByUserId) {
            // 复制属性
            LeaveResult leaveResult = new LeaveResult();
            BeanUtils.copyProperties(workLeave, leaveResult);
            // 赋值类型名称
            leaveResult.setTypeName(getTypeName(workLeave.getTypeId(),workTypes));
            // 添加到集合
            leaveResultList.add(leaveResult);
        }

        return leaveResultList;
    }

    @Override
    public Integer getHolidayCountWithTimePeriod(String startDate, String endDate) {
        log.info("WorkTimeOrderServiceImpl[]getHolidayCountWithTimePeriod[]input.param{}startDate, endDate" + startDate + "," + endDate);
        // 将两个时间字符串转为Date类型
        Date start = DateUtil.convertStrToDate(startDate, "yyyy-MM-dd");
        Date end = DateUtil.convertStrToDate(endDate, "yyyy-MM-dd");

        // 获取两个时间段内日期的集合
        List<Date> datesBetweenTwoDate = DateUtil.getDatesBetweenTwoDate(start, end);
        // 获取两个时间段内的节假日或补班日
        List<WorkHoliday> holidays = workHolidayMapper.getByDate(start, end);
        Integer count = 0;
        List<Date> weekendList = new ArrayList<>();
        for (Date date : datesBetweenTwoDate) {
            int week = DateUtil.getWeek(date);
            if (week == 1 || week == 7) {
                count ++;
                weekendList.add(date);
            }
        }

        for (WorkHoliday holiday : holidays) {
            List<Date> datesBetweenTwoDate1 = DateUtil.getDatesBetweenTwoDate(holiday.getDayStart(), holiday.getDayEnd());
            // 取交集
            datesBetweenTwoDate1.retainAll(datesBetweenTwoDate);
            // 工作日，count减
            if (holiday.getDayType() == 0) {
                count -= datesBetweenTwoDate1.size();
            }else {
                // 与周末取差集
                datesBetweenTwoDate1.removeAll(weekendList);
                count += datesBetweenTwoDate1.size();
            }
        }

        return count;
    }

    private void addWorkOrderChange(Integer content, OrderChangeVo vo) {
        WorkOrderChange workOrderChange = new WorkOrderChange();
        workOrderChange.setChangeDate(new Date()).setContent(content).setOperatorId(vo.getOperatorId()).setWorkDay(vo.getWorkDay()).setUserId(vo.getUserId()).setWorkTime(vo.getWorkTime()).setDes(vo.getDes()).setChangeReason(vo.getChangeReason());
        if (null == vo.getProjectId()) {
            WorkUser operator = workUserService.getById(vo.getOperatorId());
            workOrderChange.setType(vo.getType()).setDeptId(operator.getDeptId());
        } else {
            WorkProject workProject = workProjectService.getById(vo.getProjectId());
            workOrderChange.setProjectId(vo.getProjectId()).setType(vo.getType());
            workOrderChange.setDeptId(workProject.getDeptId());
        }
        int insert = workOrderChangeMapper.insert(workOrderChange);
        if (insert == 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INSERT_DATA_IS_FAIL);
        }
    }


    // 获取完整工单变更WorkTimeOrder
    private WorkTimeOrder getOrderChangeWorkTimeOrder(OrderChangeVo vo, WorkTimeOrder workTimeOrder) {
        WorkUser user = workUserService.getById(vo.getUserId());
        Boolean holiday = workHolidayService.isHoliday(vo.getWorkDay());
        int status = 2;
        int deptId = user.getDeptId();
        int reviewerId = vo.getOperatorId();
        int isOvertime = holiday ? 1 : 0;
        Date date = new Date();
        workTimeOrder.setStatus(status).setDeptId(deptId).setReviewerId(reviewerId).setIsOvertime(isOvertime).setModifyTime(date);
        return workTimeOrder;
    }

    private void insertWorkCollect(OrderChangeVo vo, int totalTime, Boolean isInsert, Boolean isDelete, WorkTimeOrder workTimeOrderOld) {
        if (isDelete) {
            Boolean aBoolean = workCollectService.deleteByUserIdAndWorkDay(workTimeOrderOld.getUserId(), workTimeOrderOld.getWorkDay());
            if (!aBoolean) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.FAILEDTO_DELETE_DATA);
            }
        } else {
            WorkCollect workCollect = new WorkCollect();
            int i = statusYes(vo.getUserId(), vo.getWorkDay());
            if (null == workTimeOrderOld) {

                workCollect.setUserId(vo.getUserId()).setWorkDay(vo.getWorkDay()).setTotalTime(totalTime).setStatus(i);
            } else {
                workCollect.setUserId(workTimeOrderOld.getUserId()).setWorkDay(workTimeOrderOld.getWorkDay()).setTotalTime(totalTime).setStatus(i);
            }
            Boolean aBoolean;
            if (isInsert) {
                aBoolean = workCollectService.insertCollect(workCollect);
                if (!aBoolean) {
                    throw new BaseCustomException(BASE_RESP_CODE_ENUM.INSERT_DATA_IS_FAIL);
                }
            } else {
                aBoolean = workCollectService.update(workCollect);
                if (!aBoolean) {
                    throw new BaseCustomException(BASE_RESP_CODE_ENUM.UPDATE_DATA_FAIL);
                }
            }

        }
    }

    // 判断新增的工单变更是否为空
    private void OrderChangeVoIsNull(OrderChangeVo vo, Boolean workIdIsNeed) {
        System.out.println(vo);
        if (null == vo || null ==vo.getOperatorId() || null == vo.getWorkDay() || null == vo.getWorkTime() || StringUtils.isBlank(vo.getDes()) || StringUtils.isBlank(vo.getChangeReason())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        if (!UserRoleLevelUtils.isManagerLevel(vo.getOperatorId(), LevelEnum.WORKORDER_CHANGEMANAGEMENT.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }
        if (workIdIsNeed) {
            if (null == vo.getWorkId()) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
            }
        } else if (null == vo.getUserId() ||(null == vo.getProjectId() && null == vo.getType())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        Date workDay = vo.getWorkDay();
        Date date = new Date();
        if (workDay.compareTo(date) > 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_TIME_OVER_NOW_DAY);
        }
        Integer orderChange = workSubmitAdoptService.getById(1).getOrderChange();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, -orderChange);
        Date firstDay = DateUtil.getFirstDayOfMonth(calendar.getTime());
        if (firstDay.compareTo(vo.getWorkDay()) > 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THEWORKORDERDATE_HASEXCEEDED_THECHANGERANGE);
        }
        if (vo.getWorkTime() <= 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORKORDERHOURS_MUSTBEGREATERTHAN0);
        }


    }


}
