package cn.wisenergy.service.impl;

import cn.hutool.core.collection.CollectionUtil;
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.WorkHolidayMapper;
import cn.wisenergy.mapper.WorkTimeOrderMapper;
import cn.wisenergy.mapper.WorkUserDeptMapper;
import cn.wisenergy.model.app.WorkHoliday;
import cn.wisenergy.model.app.WorkProject;
import cn.wisenergy.model.app.WorkUser;
import cn.wisenergy.model.dto.*;
import cn.wisenergy.model.enums.*;
import cn.wisenergy.service.*;
import com.alibaba.excel.util.StringUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: nh
 * @create: 2021-01-19 17:19
 **/

@Service
@Slf4j
public class StatisticsServiceImpl implements StatisticsService {
    @Autowired
    private WorkUserService workUserService;

    @Autowired
    private WorkDeptService workDeptService;

    @Autowired
    private WorkTimeOrderMapper workTimeOrderMapper;

    @Autowired
    private WorkUserDeptMapper workUserDeptMapper;

    @Autowired
    private WorkProjectService workProjectService;

    @Autowired
    private WorkHolidayMapper workHolidayMapper;

    private final static Integer DEFAULT_DEPT_ID = 1;

    @Override
    public PageInfo getDayWorkTimeOfMonth(GetMonthlyCollectParam param) {
        log.info("StatisticsServiceImpl[]getMonthlyCollect[]input.param" + param);
        if (param == null) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        //管理员用户
        WorkUser user = workUserService.getById(param.getUserId());
        if (!user.getLevel().equals(ManagerEnum.IS_SYSTEM_MANAGER.getCode())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }
        //默认时间为当月
        Integer year = param.getYear();
        Integer month = param.getMonth();
        if (StringUtils.isEmpty(param.getYear()) || StringUtils.isEmpty(param.getMonth())) {
            Date now = new Date();
            year = DateUtil.getYear(now);
            month = DateUtil.getMonth(now) + 1;
        }
        //默认部门主键为1
        Integer deptId = param.getDeptId();
        if (param.getDeptId() == null) {
            deptId = DEFAULT_DEPT_ID;
        }
        //默认当前页码为1，每页数量为10
        if (param.getCurrentPage() == null) {
            param.setCurrentPage(1);
        }
        if (param.getSize() == null) {
            param.setSize(10);
        }

        //分页获取部门下所有员工主键
        PageHelper.startPage(param.getCurrentPage(), param.getSize());
        List<Integer> userIdList = workUserDeptMapper.listByDeptId(deptId);
        PageInfo pageInfo = new PageInfo(userIdList);
        //获取员工一个月中已审核、自动审核的工单单日汇总汇总
        List<StatisticsTableDto> statisticsTableDtos = new ArrayList<>();
        for (Integer id : userIdList) {
            WorkUser workUser = workUserService.getById(id);
            //获取当月每天工时信息
            List<DayWorkTimeAndType> dayWorkTimeAndTypes = workTimeOrderMapper.listByDateAndUserId(year, month, id);
            //获取用户部门名称
            String deptName = workDeptService.getById(workUser.getDeptId()).getDeptName();
            //封装成对象
            StatisticsTableDto statisticsTableDto = new StatisticsTableDto();
            statisticsTableDto.setUserId(id);
            statisticsTableDto.setUserName(workUser.getName());
            statisticsTableDto.setDeptName(deptName);
            statisticsTableDto.setDayWorkTimeAndTypeList(dayWorkTimeAndTypes);
            statisticsTableDtos.add(statisticsTableDto);
        }
        pageInfo.setList(statisticsTableDtos);

        return pageInfo;
    }

    @Override
    public List<Object> getMonthlyStatistics(Integer userId) {
        log.info("WorkTimeOrderServiceImpl[]getMonthlyStatistics[]input.param" + userId);
        WorkUser user = workUserService.getById(userId);
        //本月第一天
        Date firstDayOfMonth = DateUtil.getCurrentFirstDayOfMonth();
        //返回数据对象
        List<Object> objects = new ArrayList<>();
        //存放查询条件
        Map<String, Object> map = new HashMap<>();
        //用户是项目或部门级别，查询审批统计
        if (user.getLevel().equals(ManagerEnum.IS_PROJECT_DIRECTOR.getCode()) ||
                user.getLevel().equals(ManagerEnum.IS_DEPARTMENT_DIRECTOR.getCode())) {
            //以审批人、审核状态、开始时间查询本月审批数量
            map.put("reviewerId", userId);
            map.put("status", WorkOrderStatus.ALREADY_AUDIT.getCode());
            map.put("startDay", firstDayOfMonth);
            Integer completedCount = workTimeOrderMapper.getCountByCondition(map);

            //本月驳回未重报数量
            map.replace("status", WorkOrderStatus.TURN_DOWN.getCode());
            Integer rejectAndNotResubmit = workTimeOrderMapper.getCountByCondition(map);

            //项目级别，获取所管理项目,
            if (user.getLevel().equals(ManagerEnum.IS_PROJECT_DIRECTOR.getCode())) {
                List<WorkProject> projects = workProjectService.getUserManageProjects(userId);
                if (CollectionUtil.isNotEmpty(projects)) {
                    List<Integer> projectIds = projects.stream().map(WorkProject::getId).collect(Collectors.toList());
                    map.put("projectIds", projectIds);
                }
            }
            //部门级别
            if (user.getLevel().equals(ManagerEnum.IS_DEPARTMENT_DIRECTOR.getCode())) {
                map.put("deptId", user.getDeptId());
                //填报项目类型编码
                int[] workOrderTypeArray = {WorkOrderType.EXTERNAL_WORK.getCode(), WorkOrderType.INTERNAL_WORK.getCode(), WorkOrderType.OTHER_NOT_PROJECT_BUSINESS.getCode()};
                map.put("typeArray", workOrderTypeArray);
            }
            //待审核包括：新提交和重新提交的
            List<Integer> statusArray = new ArrayList<>();
            statusArray.add(WorkOrderStatus.WAIT_AUDIT.getCode());
            statusArray.add(WorkOrderStatus.RE_SUBMIT.getCode());
            map.remove("reviewerId");
            map.remove("status");
            //本月未审批数量查询
            map.put("statusArray", statusArray);
            Integer notCompletedCount = workTimeOrderMapper.getCountByCondition(map);
            //所有查询结果封装进对象
            ApprovalStatistics approvalStatistics = new ApprovalStatistics();
            approvalStatistics.setApprovalCount(completedCount);
            approvalStatistics.setRejectNotSubmit(rejectAndNotResubmit);
            approvalStatistics.setNotApprovalCount(notCompletedCount);
            objects.add(approvalStatistics);
        }
        //用户是普通用户或项目级别用户，查询填报统计
        if (user.getLevel().equals(ManagerEnum.NOT_MANAGER.getCode()) ||
                user.getLevel().equals(ManagerEnum.IS_PROJECT_DIRECTOR.getCode())) {
            // 本月应填报日期
            List<Date> currentMonthWorkDays = this.currentMonthWorkDays();
            // 本月已填报日期
            List<Date> currentMonthFilledDays = currentMonthFilledDays(userId);
            // 本月未填报日期
            currentMonthWorkDays.removeAll(currentMonthFilledDays);
            int notFilledCount = currentMonthWorkDays.size();
            //本月被现存驳回数
            map.clear();
            map.put("status", 3);
            map.put("userId", userId);
            map.put("startDay", firstDayOfMonth);
            Integer countByCondition = workTimeOrderMapper.getCountByCondition(map);

            List<MonthlyWorkingHoursStatistics> monthlyWorkingHoursStatistics = workTimeOrderMapper.statisticsByProjectType(userId, firstDayOfMonth);
            for (MonthlyWorkingHoursStatistics monthlyWorkingHoursStatistic : monthlyWorkingHoursStatistics) {
                monthlyWorkingHoursStatistic.setNotFilledCount(notFilledCount);
                monthlyWorkingHoursStatistic.setRejectCount(countByCondition);
            }

            objects.add(monthlyWorkingHoursStatistics);
        }
        return objects;
    }

    @Override
    public List<WorkTimeAndCostCollect> getCurrentMonthWorkTimeCollect(Integer userId, String startTime) {
        log.info("StatisticsServiceImpl[]getCurrentMonthWorkTimeCollect[]input.param" + userId + startTime);
        if (userId == null) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        WorkUser user = workUserService.getById(userId);
        if (user.getLevel().equals(ManagerEnum.NOT_MANAGER.getCode())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }
        //查询用户管理的项目
        List<WorkProject> userManageProjects = workProjectService.getUserManageProjects(userId);
        if (CollectionUtil.isEmpty(userManageProjects)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.MANAGER_NOT_PROJECT);
        }
        //获取项目集合中所有项目的项目主键
        List<Integer> projectIds = userManageProjects.stream().map(WorkProject::getId).collect(Collectors.toList());

        List<WorkTimeAndCostCollect> collect = workTimeOrderMapper.getWorkTimeAndCostCollect(projectIds, startTime);
        return collect;
    }

    //获取本月应上班日期
    public List<Date> currentMonthWorkDays() {
        log.info("StatisticsServiceImpl[]currentMonthWorkDays[]input.method");
        //当前时间
        Date now = new Date();
        //本月第一天
        Date firstDayOfMonth = DateUtil.getFirstDayOfMonth(now);
        //本月第一天到当日的日期集合
        List<Date> workDays = DateUtil.getDatesBetweenTwoDate(firstDayOfMonth, now);
        //除去周末
        Iterator<Date> iterator = workDays.iterator();
        while (iterator.hasNext()) {
            int week = DateUtil.getWeek(iterator.next());
            if (week == 6 || week == 7) {
                iterator.remove();
            }
        }
        //获取当月的节日和周末上班日期
        List<WorkHoliday> specialDates = workHolidayMapper.getByDate(firstDayOfMonth, now);
        if (CollectionUtil.isEmpty(specialDates)) {
            return workDays;
        }
        for (WorkHoliday specialDate : specialDates) {
            List<Date> isWorkDays = DateUtil.getDatesBetweenTwoDate(specialDate.getDayStart(), specialDate.getDayEnd());
            //获取的是工作日
            if (specialDate.getDayType().equals(HolidayTypeEnum.WORKING_DAY.getCode())) {
                //在本月应上班集合中加上这天，一般都是放假前后的周末调整上班
                workDays.addAll(isWorkDays);
            }else {
                //否则就除去假日
                workDays.removeAll(isWorkDays);
            }
        }
        return workDays;
    }

    //获取用户本月已填报的日期
    public List<Date> currentMonthFilledDays(Integer userId) {
        log.info("StatisticsServiceImpl[]currentMonthFilledDays[]input.method");
        Date firstDayOfMonth = DateUtil.getCurrentFirstDayOfMonth();
        List<Date> currentMonthFilledDays = workTimeOrderMapper.getDaysByDateAndStatus(firstDayOfMonth,userId);
        return currentMonthFilledDays;
    }

}
