package cn.wisenergy.service.impl;

import cn.wisenergy.common.utils.DateUtil;
import cn.wisenergy.common.utils.exception.BASE_RESP_CODE_ENUM;
import cn.wisenergy.common.utils.exception.BaseCustomException;
import cn.wisenergy.mapper.WorkTimeOrderMapper;
import cn.wisenergy.model.app.*;
import cn.wisenergy.model.dto.CreateWorkOrderDto;
import cn.wisenergy.model.dto.ExamineGroupbyProjectDto;
import cn.wisenergy.model.dto.SubtotalDto;
import cn.wisenergy.model.dto.WorkTimeOrderDto;
import cn.wisenergy.service.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
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 org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

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

    @Autowired
    private WorkTimeOrderMapper workTimeOrderMapper;

    @Autowired
    private WorkProjectService workProjectService;

    @Autowired
    private WorkSbumitAdoptService workSbumitAdoptService;

    @Autowired
    private WorkCollectService workCollectService;

    @Autowired
    private WorkUserService workUserService;

    @Autowired
    private WorkHolidayService workHolidayService;

    @Autowired
    private WorkUserDeptService workUserDeptService;

    @Autowired
    private WorkUserProjectService workUserProjectService;

    @Autowired
    private WorkDeptService workDeptService;


    /**
     * 功能; 获取某日被驳回说明
     *
     * @param userId
     * @param workDay
     * @return
     */
    @Override
    public List<WorkTimeOrder> getByDay(Integer userId, Date workDay) {
        log.info("WorkTimeOrderServiceImpl[]getDayRejectReason[]input.param.userId:{},workDay:{}" + userId, workDay);
        if (null == userId || StringUtils.isEmpty(workDay)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        List<WorkTimeOrder> wtos = workTimeOrderMapper.getByDay(userId, workDay);
        if (CollectionUtils.isEmpty(wtos)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_ORDER_INFO_IS_NULL);
        }
        return wtos;
    }

    /**
     * 功能：获取某日填报小计
     *
     * @param userId
     * @param workDay
     * @return
     */
    @Override
    public SubtotalDto getSubtotalReport(Integer userId, Date workDay) {
        log.info("WorkTimeOrderServiceImpl[]getSubtotalReport[]input.param.userId:{},workDay:{}" + userId, workDay);
        if (null == userId || StringUtils.isEmpty(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;
        String reason = "";
        int rejectMonth = 0;
        subtotalDto.setUserId(userId);
        subtotalDto.setWorkDay(workDay);
        for (WorkTimeOrder wto : workTimeOrders) {
            totalTime += wto.getWorkTime();
            if (null != wto.getReason()) {
                reason = wto.getProjectName() + ":" + wto.getReason() + "  ";
            }
            if (3 == wto.getStatus()) {
                rejectMonth += 1;
            }
        }
        subtotalDto.setReason(reason);
        subtotalDto.setTotalTime(totalTime);
        subtotalDto.setRejectMonth(rejectMonth);
        return subtotalDto;
    }

    /**
     * 功能; 获取某日填报信息
     *
     * @param userId
     * @param workDay
     * @return DTO
     */
    @Override
    public List<WorkTimeOrderDto> getByDayToDto(Integer userId, Date workDay) {
        log.info("WorkTimeOrderServiceImpl[]getByDayToDto[]input.param.userId:{},workDay:{}" + userId, workDay);
        List<WorkTimeOrder> wtos = getByDay(userId, workDay);
        List<WorkTimeOrderDto> dtos = new ArrayList<>();
        WorkProject workProject = new WorkProject();
        for (WorkTimeOrder wto : wtos) {
            WorkTimeOrderDto dto = new WorkTimeOrderDto();
            BeanUtils.copyProperties(wto, dto);
            dto.setProjectManagerName(getManagerNameByOrder(wto));
            dtos.add(dto);
        }
        return dtos;
    }

    /**
     * 功能：工时填报
     *
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public List<WorkTimeOrderDto> add(CreateWorkOrderDto dto) {
        log.info("WorkTimeOrderServiceImpl[]add[]input.param.CreateWorkOrderDto:{}" + dto);
        if (null == dto || CollectionUtils.isEmpty(dto.getWorkTimeOrders())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }

        // 1.检查工单
        this.checkWorkOrderInfo(dto.getWorkTimeOrders());

        // 2.保存工单信息
        List<WorkTimeOrderDto> result = this.saveWorkOrderInfo(dto.getWorkTimeOrders());
        log.info("WorkOrderServiceImpl[]add[]add.success");
        return result;
    }

    /**
     * 功能： 驳回重新填报
     *
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public List<WorkTimeOrderDto> update(CreateWorkOrderDto dto) {
        log.info("WorkTimeOrderServiceImpl[]update[]input.param.CreateWorkOrderDto:{}" + dto);
        if (null == dto || CollectionUtils.isEmpty(dto.getWorkTimeOrders())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }

        WorkSbumitAdopt workSbumitAdopt = workSbumitAdoptService.getById(1);
        Integer submitTime = workSbumitAdopt.getSubmitTime();
        for (WorkTimeOrderDto workTimeOrderDto : dto.getWorkTimeOrders()) {
            if (null == workTimeOrderDto.getDes()) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.DES_NOT_NULL);
            }
            Date modifyTime = workTimeOrderMapper.selectById(workTimeOrderDto.getWorkId()).getModifyTime();
            // 判断是否已经驳回三天
            if (new Date().getTime() - DateUtil.getStartOfDay(modifyTime).getTime() > submitTime * 24 * 60 * 60 * 1000) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_DAY_THAN_DATE);
            }

            WorkTimeOrder workTimeOrder = new WorkTimeOrder();
            BeanUtils.copyProperties(workTimeOrderDto, workTimeOrder);
            workTimeOrder.setStatus(4);
            // 获取用户名
            workTimeOrder.setUserName(workUserService.getById(workTimeOrder.getUserId()).getName());
            workTimeOrder.setProjectName(workProjectService.getById(workTimeOrder.getProjectId()).getProjectName());
            // 获取部门id
            workTimeOrder.setDeptId(workUserDeptService.getDeptIdByUserId(workTimeOrder.getUserId()));
            Date workDay = workTimeOrder.getWorkDay();
            // 默认正常工时
            workTimeOrder.setIsOvertime(0);
            if (workHolidayService.isHoliday(workDay)) {
                workTimeOrder.setIsOvertime(1);
            }
            int iRow = workTimeOrderMapper.updateById(workTimeOrder);
            if (0 == iRow) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.UPDATE_DATA_FAIL);
            }
            WorkCollect workCollect = new WorkCollect();
            BeanUtils.copyProperties(workTimeOrder, workCollect);
            workCollect.setStatus(1);
            workCollectService.update(workCollect);
        }

        return dto.getWorkTimeOrders();
    }

    /**
     * 功能：获取待审批数据
     *
     * @param userId
     * @return
     */
    @Override
    public List<ExamineGroupbyProjectDto> getExamine(Integer userId, Integer projectId, Integer type, Integer page, Integer size, Integer status) {
        log.info("WorkOrderServiceImpl[]getExamine[]input.param.userId:{},projectId:{},type:{},page:{},size:{},status:{}" + userId, projectId, type, page, size, status);
        if (null == userId) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        // 判断当前用户是否为管理
        WorkUser user = workUserService.getById(userId);
        if (0 == user.getLevel()) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }
        // PC端
        if (null != page && null != size) {
            return pageExamine(user, projectId, type, page, size, status);
        }

        type = null == type ? 5 : type;
        // 部门经理审核
        if (2 == user.getLevel()) {
            Integer deptId = workUserDeptService.getDeptIdByUserId(userId);
            QueryWrapper<WorkTimeOrder> wrapper = new QueryWrapper<>();
            wrapper.eq("dept_id", deptId);
            wrapper.in("status", 1, 4);
            wrapper.eq("type", type);
            List<WorkTimeOrder> workTimeOrders = workTimeOrderMapper.selectList(wrapper);
            if (CollectionUtils.isEmpty(workTimeOrders)) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_ORDER_END);
            }
            List<ExamineGroupbyProjectDto> egpds = new ArrayList<>();
            for (WorkTimeOrder workTimeOrder : workTimeOrders) {
                ExamineGroupbyProjectDto dto = new ExamineGroupbyProjectDto();
                BeanUtils.copyProperties(workTimeOrder, dto);
                egpds.add(dto);
            }
            return egpds;
        }
        // 项目经理审核
        if (null == projectId) {
            projectId = workUserProjectService.getProjectIdByUserId(userId).get(0);
            return getExamineGroupbyProjectDto(userId, projectId);
        }
        return getExamineGroupbyProjectDto(userId, projectId);
    }

    /**
     * 功能：批量审批
     *
     * @param ids
     * @return
     */
    @Transactional
    @Override
    public Boolean examinsByIds(Integer reviewerId, List<Integer> ids) {
        log.info("WorkOrderServiceImpl[]examinsByIds[]input.param.ids:" + ids);
        if (CollectionUtils.isEmpty(ids)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        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);
        Integer userId = null;
        Date workDay = null;
        for (WorkTimeOrder workTimeOrder : workTimeOrders) {
            userId = workTimeOrder.getUserId();
            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(2);
            workCollect.setTotalTime(0);
            workCollectService.update(workCollect);
        }
        return true;
    }

    /**
     * 功能： 驳回
     *
     * @param 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.isEmpty(reason)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        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(3);
        workCollect.setTotalTime(0);
        Boolean aBoolean = workCollectService.update(workCollect);
        return aBoolean;
    }

    /**
     * 功能：查询驳回未提交的
     *
     * @param userId
     * @return
     */
    @Transactional
    @Override
    public List<WorkTimeOrderDto> rejectNotSubmit(Integer userId) {
        log.info("WorkOrderServiceImpl[]rejectById[]input.param.id:{}" + userId);
        if (null == userId) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        WorkUser user = workUserService.getById(userId);
        if (0 == user.getLevel()) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }
        QueryWrapper<WorkTimeOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("reviewer_id", userId);
        wrapper.eq("status", 3);
        List<WorkTimeOrder> workTimeOrders = workTimeOrderMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(workTimeOrders)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_ORDER_INFO_IS_NULL);
        }
        ArrayList<WorkTimeOrderDto> dtos = new ArrayList<>();
        for (WorkTimeOrder workTimeOrder : workTimeOrders) {
            WorkTimeOrderDto dto = new WorkTimeOrderDto();
            BeanUtils.copyProperties(workTimeOrder, dto);
            dto.setProjectManagerName(getManagerNameByOrder(workTimeOrder));
            dtos.add(dto);
        }
        return dtos;
    }

    public List<ExamineGroupbyProjectDto> getExamineGroupbyProjectDto(Integer userId, Integer projectId) {
        QueryWrapper<WorkTimeOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("project_id", projectId);
        wrapper.in("status", 1, 4);
        wrapper.orderByDesc("work_day");
        List<WorkTimeOrder> workTimeOrders = workTimeOrderMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(workTimeOrders)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_ORDER_END);
        }
        String projectName = workTimeOrders.get(0).getProjectName();
        List<ExamineGroupbyProjectDto> egpds = new ArrayList<>();
        for (WorkTimeOrder workTimeOrder : workTimeOrders) {
            ExamineGroupbyProjectDto dto = new ExamineGroupbyProjectDto();
            BeanUtils.copyProperties(workTimeOrder, dto);
            egpds.add(dto);
        }

        return egpds;
    }


    public void checkWorkOrderInfo(List<WorkTimeOrderDto> list) {
        log.info("WorkOrderServiceImpl[]checkWorkOrderInfo[]input.method");
        // 1、工单时间不能大于当前天
        Date date = new Date();
        WorkSbumitAdopt workSbumitAdopt = workSbumitAdoptService.getById(1);
        Integer submitTime = workSbumitAdopt.getSubmitTime();
        for (WorkTimeOrderDto dto : list) {
            if (null == dto.getDes()) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.DES_NOT_NULL);
            }
            if (thanDate(dto.getWorkDay())) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_TIME_OVER_NOW_DAY);
            }
            // 2、默认设置超过系统默认3天（包括驳回3天）未填报的工时将不能填报
            if (date.getTime() - dto.getWorkDay().getTime() > submitTime * 24 * 60 * 60 * 1000) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_DAY_THAN_DATE);
            }
        }
        //3.每天工时累加不得超过八小时
        int count = 0;
        for (WorkTimeOrderDto workOrder : list) {
            count = count + workOrder.getWorkTime();
            if (count > 8) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.WORK_TIME_NOT_OVER_EIGHT);
            }
        }
    }

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

    public List<WorkTimeOrderDto> saveWorkOrderInfo(List<WorkTimeOrderDto> list) {
        log.info("WorkOrderServiceImpl[]saveWorkOrderInfo[]input.method");
        int totalTime = 0;
        int status = 1;
        //根据用户id,获取用户信息
        for (WorkTimeOrderDto dto : list) {
            WorkTimeOrder workTimeOrder = new WorkTimeOrder();
            // 获取用户名
            dto.setUserName(workUserService.getById(dto.getUserId()).getName());
            // 获取项目名
            if ((1 == dto.getType() || 2 == dto.getType()) && null == dto.getProjectId()) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.NO_JOIN_EVERY_PROJECT_PLASE_JION);
            }
            if (null != dto.getProjectId()) {
                dto.setProjectName(workProjectService.getById(dto.getProjectId()).getProjectName());
            }
            if (null == dto.getProjectId()) {
                dto.setProjectName(getTypeName(dto.getType()));
            }

            BeanUtils.copyProperties(dto, workTimeOrder);

            // 获取部门id
            workTimeOrder.setDeptId(workUserDeptService.getDeptIdByUserId(workTimeOrder.getUserId()));
            Date workDay = workTimeOrder.getWorkDay();
            // 默认正常工时
            workTimeOrder.setIsOvertime(0);
            if (workHolidayService.isHoliday(workDay)) {
                workTimeOrder.setIsOvertime(1);
            }
            // 如果是请假或者调休直接通过
            if (3 == workTimeOrder.getType() || 4 == workTimeOrder.getType()) {
                status = 2;
                workTimeOrder.setProjectName(null);
                workTimeOrder.setProjectId(null);
            }
            workTimeOrder.setStatus(status);


            int saveRow = workTimeOrderMapper.save(workTimeOrder);
            if (0 == saveRow) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.INSERT_DATA_IS_FAIL);
            }
            totalTime += workTimeOrder.getWorkTime();
        }
        WorkCollect workCollect = new WorkCollect();
        BeanUtils.copyProperties(list.get(0), workCollect);
        workCollect.setTotalTime(totalTime);
        workCollect.setStatus(status);
        if (!workCollectService.insertCollect(workCollect)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INSERT_DATA_IS_FAIL);
        }
        return list;
    }

    public String getTypeName(Integer type) {
        if (type == 5) {
            return "外部商务、技术交流";
        }
        if (type == 6) {
            return "内部培训、技术准备、管理";
        }
        if (type == 7) {
            return "其他非项目/商机工作";
        }
        return null;
    }

    // 审批分页
    public List<ExamineGroupbyProjectDto> pageExamine(WorkUser user, Integer projectId, Integer type, Integer page, Integer size, Integer status) {
        log.info("WorkOrderServiceImpl[]pageExamine[]input.param.user:{},projectId:{},type:{},page:{},size:{},status:{}" + user, projectId, type, page, size, status);
        PageHelper.startPage(page, size);
        List<ExamineGroupbyProjectDto> egpds = new ArrayList<>();
        List<WorkTimeOrder> workTimeOrders = null;
        Integer level = user.getLevel();
        List<Integer> types = new ArrayList<>();
        // 项目经理
        if (1 == level) {

            types = type == null ? Arrays.asList(1, 2, 3, 4) : Arrays.asList(type);
            workTimeOrders = workTimeOrderMapper.queryByPage(status, projectId, types);
        }
        // 部门经理
        if (2 == level) {
            types = type == null ? Arrays.asList(3, 4, 5, 6) : Arrays.asList(type);
            workTimeOrders = workTimeOrderMapper.queryByPage(status, null, types);
        }
        for (WorkTimeOrder workTimeOrder : workTimeOrders) {
            ExamineGroupbyProjectDto egpd = new ExamineGroupbyProjectDto();
            BeanUtils.copyProperties(workTimeOrder, egpd);
            egpds.add(egpd);
        }
        return egpds;
    }


    // 根据工单获取管理员
    public String getManagerNameByOrder(WorkTimeOrder wto) {
        if (1 == wto.getType() || 2 == wto.getType()) {
            WorkProject workProject = workProjectService.getById(wto.getProjectId());
            return workProject != null ? workProject.getManagerName() : "";
        }
        if (1 != wto.getType() || 2 != wto.getType()) {
            String ManagerName = workUserService.getById(
                    workDeptService.getById(wto.getDeptId()
                    ).getDeptManagerId()).getName();
            return ManagerName;
        }
        return null;
    }
}
