package com.mortals.xhx.daemon.task;

import cn.hutool.core.date.DateUtil;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.service.ITask;
import com.mortals.framework.service.ITaskExcuteService;
import com.mortals.xhx.base.system.user.model.UserEntity;
import com.mortals.xhx.common.code.StaffSatusEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.module.attendance.model.*;
import com.mortals.xhx.module.attendance.service.AttendanceGroupFixedworkService;
import com.mortals.xhx.module.attendance.service.AttendanceGroupStaffService;
import com.mortals.xhx.module.attendance.service.AttendanceRecordHikService;
import com.mortals.xhx.module.holiday.model.HolidayEntity;
import com.mortals.xhx.module.holiday.model.HolidayQuery;
import com.mortals.xhx.module.holiday.service.HolidayService;
import com.mortals.xhx.module.staff.model.StaffEntity;
import com.mortals.xhx.module.staff.service.StaffService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

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

/**
 * 定时计算当天全缺席人员
 */
@Slf4j
@Service("CalculateDayAttendTask")
public class CalculateDayAttendTaskImpl implements ITaskExcuteService {

    @Autowired
    private AttendanceRecordHikService recordHikService;
    @Autowired
    private StaffService staffService;
    @Autowired
    private AttendanceGroupStaffService attendanceGroupStaffService;
    @Autowired
    private AttendanceGroupFixedworkService groupFixedworkService;
    @Autowired
    private HolidayService holidayService;


    @Override
    public void excuteTask(ITask task) throws AppException {
        //查询当日考勤记录，查询未考勤人员，构造一条假记录方便计算
        AttendanceRecordHikQuery recordHikQuery = new AttendanceRecordHikQuery();
        recordHikQuery.setAttendanceDateStart(DateUtil.today());
        recordHikQuery.setAttendanceDateEnd(DateUtil.today());
        Set<Long> attendStaffSet = recordHikService.find(recordHikQuery).stream().map(i -> i.getStaffId()).distinct().collect(Collectors.toSet());
        Map<Long, List<AttendanceGroupStaffEntity>> groupStaffCollect = attendanceGroupStaffService.find(new AttendanceGroupStaffQuery()).stream().collect(Collectors.groupingBy(x -> x.getGroupId()));
        Iterator<Map.Entry<Long, List<AttendanceGroupStaffEntity>>> iterator = groupStaffCollect.entrySet().iterator();

        while (iterator.hasNext()) {
            Map.Entry<Long, List<AttendanceGroupStaffEntity>> item = iterator.next();
            //分组查看当前人
            Long groupId = item.getKey();
            AttendanceGroupFixedworkEntity attendanceGroupFixedworkEntity = groupFixedworkService.selectOne(new AttendanceGroupFixedworkQuery().groupId(groupId));
            String week = this.getWeek(new Date());
            Long weekClassId = this.getWeekClassId(attendanceGroupFixedworkEntity, week);
            //weekClassId为-1 则不在考勤
            //对于节假日 分两种情况。
            // 1.当前是工作日，但是是节假日。则不做考勤continue;
            // 2.当前是非工作日，但是由于节假日情况，需要补班，需要做考勤
            //weekClassId == -1L 当日不需要考勤的 与节假日冲突的 以节假日为准
            Boolean checkWorkByHoliday = checkWorkByHoliday();
            Boolean checkHolidayByWorkDay = checkHolidayByWorkDay();
            if (weekClassId == -1L) {
                //跳过本次循环
                log.info("当前日期不在考勤时间范围内，不做处理！");
                if (!checkWorkByHoliday) {
                    continue;
                }
            } else {
                if (checkHolidayByWorkDay) {
                    //本来当天是需要考勤的，但是是节假日，则不计算考勤
                    continue;
                }
            }

            List<AttendanceGroupStaffEntity> groupStaffList = item.getValue();
            //查看当前需要考勤但是没有记录的人
            List<Long> unAttendStaffIdList = groupStaffList.stream().filter(f -> !attendStaffSet.contains(f.getStaffId())).map(i -> i.getStaffId()).collect(Collectors.toList());
            if (!ObjectUtils.isEmpty(unAttendStaffIdList)) {
                for (Long staffId : unAttendStaffIdList) {
                    StaffEntity staffCache = staffService.getCache(staffId.toString());
                    if (!ObjectUtils.isEmpty(staffCache) && StaffSatusEnum.离职.getValue() != staffCache.getStatus()) {
                        //构建考勤记录  判断当前人是否离职，如果非离职 构建记录
                        AttendanceRecordHikEntity recordHikEntity = new AttendanceRecordHikEntity();
                        recordHikEntity.initAttrValue();
                        recordHikEntity.setStaffId(staffCache.getId());
                        recordHikEntity.setStaffName(staffCache.getName());
                        recordHikEntity.setWorkNum(staffCache.getWorkNum());
                        recordHikEntity.setDeptId(staffCache.getDeptId());
                        recordHikEntity.setDeptName(staffCache.getDeptName());
                        recordHikEntity.setSalaId(staffCache.getSalaId());
                        recordHikEntity.setSalaName(staffCache.getSalaName());
                        recordHikEntity.setPositionId(staffCache.getPositionId());
                        recordHikEntity.setPositionName(staffCache.getPositionName());
                        recordHikEntity.setAttendanceGroupId(groupId);
                        recordHikEntity.setAttendanceDate(DateUtil.parseDate(DateUtil.today()).toJdkDate());
                        recordHikEntity.setAttendanceAddress("自定义地点");
                        recordHikEntity.setEventSource("当日未有记录虚增考勤记录！");
                        recordHikEntity.setCreateTime(new Date());
                        recordHikEntity.setCreateUserId(1L);

                        try {
                            recordHikService.getDao().insert(recordHikEntity);
                        } catch (Exception e) {
                            log.error(e.getMessage());
                        }
                    } else {
                        log.error("未找到当前员工，staffId:{}", staffId);
                    }
                }
            }
        }

        calculateAttendByDay();
    }

    private Boolean checkWorkByHoliday() {
        Boolean bool = false;
        HolidayQuery holidayQuery = new HolidayQuery();
        holidayQuery.setStartTimeStart(DateUtil.today());
        holidayQuery.setStartTimeEnd(DateUtil.today());
        HolidayEntity holidayEntity = holidayService.selectOne(holidayQuery);
        if (!ObjectUtils.isEmpty(holidayEntity)) {
            Integer workorholiday = holidayEntity.getWorkorholiday();
            if (workorholiday == YesNoEnum.YES.getValue()) {
                bool = true;
            }
        }

        return bool;
    }

    private Boolean checkHolidayByWorkDay() {
        Boolean bool = false;
        HolidayQuery holidayQuery = new HolidayQuery();
        holidayQuery.setStartTimeStart(DateUtil.today());
        holidayQuery.setStartTimeEnd(DateUtil.today());
        HolidayEntity holidayEntity = holidayService.selectOne(holidayQuery);
        if (!ObjectUtils.isEmpty(holidayEntity)) {
            Integer workorholiday = holidayEntity.getWorkorholiday();
            if (workorholiday == YesNoEnum.NO.getValue()) {
                bool = true;
            }
        }

        return bool;
    }


    private void calculateAttendByDay() {
        Context context = new Context();
        UserEntity userEntity = new UserEntity();
        userEntity.setCreateUserId(1L);
        userEntity.setId(1L);
        userEntity.setCreateUserName("admin");
        userEntity.setCreateTime(new Date());
        context.setUser(userEntity);
        AttendanceRecordHikQuery recordHikQuery = new AttendanceRecordHikQuery();

        // Date todayStart = DateUtil.offsetHour(new Date(), -5).toJdkDate();
        //  recordHikQuery.setAttendanceDateStart(DateUtils.getCurrStrDate());
        recordHikQuery.setAttendanceDateStart(DateUtil.today());
        recordHikQuery.setAttendanceDateEnd(DateUtil.today());
        try {
            recordHikService.addAttendanceRecordByQuery(recordHikQuery, context);
        } catch (Exception e) {
            log.error("计算考勤异常", e);
        }
    }

    protected String getWeek(Date date) {
        // Get the day of the week (1 = Sunday, 2 = Monday, ..., 7 = Saturday)
        int dayOfWeek = DateUtil.dayOfWeek(date);
        // Map the numeric day of the week to its corresponding Chinese name
        String[] dayOfWeekNames = new String[]{
                "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"
        };
        // Get the Chinese name of the day of the week
        String dayOfWeekName = dayOfWeekNames[dayOfWeek - 1];
        return dayOfWeekName;
    }

    /**
     * 获取通过星期获取班次id  如果返参为-1 则不在考勤
     *
     * @return
     */
    protected Long getWeekClassId(AttendanceGroupFixedworkEntity attendanceGroupFixedworkEntity, String week) {
        Long weekClassId = 0L;
        switch (week) {
            case "星期一":
                if (attendanceGroupFixedworkEntity.getMonday() == 0) {
                    weekClassId = -1L;
                    return weekClassId;
                }
                weekClassId = attendanceGroupFixedworkEntity.getMondayClassId();
                break;
            case "星期二":
                if (attendanceGroupFixedworkEntity.getTuesday() == 0) {
                    weekClassId = -1L;
                    return weekClassId;
                }
                weekClassId = attendanceGroupFixedworkEntity.getTuesdayClassId();
                break;
            case "星期三":
                if (attendanceGroupFixedworkEntity.getWednesday() == 0) {
                    weekClassId = -1L;
                    return weekClassId;
                }
                weekClassId = attendanceGroupFixedworkEntity.getWednesdayClassId();
                break;
            case "星期四":
                if (attendanceGroupFixedworkEntity.getThursday() == 0) {
                    weekClassId = -1L;
                    return weekClassId;
                }
                weekClassId = attendanceGroupFixedworkEntity.getThursdayClassId();
                break;
            case "星期五":
                if (attendanceGroupFixedworkEntity.getFriday() == 0) {
                    weekClassId = -1L;
                    return weekClassId;
                }
                weekClassId = attendanceGroupFixedworkEntity.getFridayClassId();
                break;
            case "星期六":
                if (attendanceGroupFixedworkEntity.getSaturday() == 0) {
                    weekClassId = -1L;
                    return weekClassId;
                }
                weekClassId = attendanceGroupFixedworkEntity.getSaturdayClassId();
                break;
            case "星期日":
                if (attendanceGroupFixedworkEntity.getSunday() == 0) {
                    weekClassId = -1L;
                    return weekClassId;
                }
                weekClassId = attendanceGroupFixedworkEntity.getSundayClassId();
                break;
        }
        return weekClassId;
    }


    @Override
    public void stopTask(ITask task) throws AppException {

    }
}
