package com.mortals.xhx.module.attendance.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.mortals.framework.model.PageInfo;
import com.mortals.framework.service.ICacheService;
import com.mortals.framework.util.DataUtil;
import com.mortals.framework.util.DateUtils;
import com.mortals.framework.util.StringUtils;
import com.mortals.xhx.busiz.h5.req.AttendSaveReq;
import com.mortals.xhx.busiz.h5.web.ApiWebPerformController;
import com.mortals.xhx.common.code.AppealResultEnum;
import com.mortals.xhx.common.code.ErrorStatusEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.module.attendance.model.*;
import com.mortals.xhx.module.attendance.model.vo.AttendanceSummaryQuery;
import com.mortals.xhx.module.attendance.service.*;
import com.mortals.xhx.module.perform.service.PerformAttendRecordService;
import com.mortals.xhx.module.staff.service.StaffService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.xhx.module.attendance.dao.AttendanceRecordErrorDao;
import org.springframework.util.ObjectUtils;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.mortals.xhx.common.key.RedisKey.KEY_ATTENDANCE_STAT_CACHE;

/**
 * AttendanceRecordErrorService
 * 考勤打卡记录异常信息 service实现
 *
 * @author zxfei
 * @date 2023-04-08
 */
@Service("attendanceRecordErrorService")
public class AttendanceRecordErrorServiceImpl extends AbstractCRUDServiceImpl<AttendanceRecordErrorDao, AttendanceRecordErrorEntity, Long> implements AttendanceRecordErrorService {

    @Autowired
    private AttendanceClassDetailService classDetailService;

    @Autowired
    private AttendanceClassService attendanceClassService;
    @Autowired
    private PerformAttendRecordService performAttendRecordService;

    @Autowired
    private ApiWebPerformController apiWebPerformController;
    @Autowired
    private StaffService staffService;
    @Autowired
    private AttendanceStatService attendanceStatService;
    @Autowired
    private ICacheService cacheService;
    @Autowired
    private AttendanceLeaveRecordService attendanceLeaveRecordService;


    @Override
    protected void findAfter(AttendanceRecordErrorEntity params, PageInfo pageInfo, Context context, List<AttendanceRecordErrorEntity> list) throws AppException {

        list.forEach(item -> {
            AttendanceClassDetailEntity attendanceClassDetailEntity = classDetailService.get(item.getShiftsId(), context);

            if (!ObjectUtils.isEmpty(attendanceClassDetailEntity)) {
                String str = DateUtil.formatTime(item.getGoOffDateTime());
                String goStr = DateUtil.formatTime(attendanceClassDetailEntity.getGoWorkDate());
                String offStr = DateUtil.formatTime(attendanceClassDetailEntity.getOffWorkDate());

                if (!ObjectUtils.isEmpty(str) && str.equals(goStr)) {
                    item.setGoOrOff("上班");
                }
                if (!ObjectUtils.isEmpty(str) && str.equals(offStr)) {
                    item.setGoOrOff("下班");
                }
                if (ObjectUtils.isEmpty(item.getGoOrOff())) {
                    item.setGoOrOff("");
                }
            } else {
                item.setGoOrOff("");
            }
        });
    }

    @Override
    protected void updateAfter(AttendanceRecordErrorEntity entity, Context context) throws AppException {
        if (YesNoEnum.YES.getValue() == entity.getProcessStatus()) {
            entity= this.get(entity.getId());
            //判断后打绩效
            String ruleCode = "";
            if (ErrorStatusEnum.早退.getValue() == DataUtil.converStr2Int(entity.getProcessResult(), 3)) {
                if (!ObjectUtils.isEmpty(entity.getErrorDateTime()) && !ObjectUtils.isEmpty(entity.getGoOffDateTime())) {
                    //判断时间差定义
                    Long earlyMin = DateUtil.between(entity.getErrorDateTime(), entity.getGoOffDateTime(), DateUnit.MINUTE);

                    if (earlyMin >= 0L && earlyMin < 5L) {
                        //早退5分钟内
                        ruleCode = "ATTEND1002";
                    }
                    if (earlyMin >= 5L && earlyMin < 60L) {
                        //早退5分钟内
                        ruleCode = "ATTEND1004";
                    }
                    if (earlyMin >= 60L) {
                        //早退5分钟内
                        ruleCode = "ATTEND1006";
                    }
                }else {
                    ruleCode = "ATTEND1002";
                }
            } else if (ErrorStatusEnum.迟到.getValue() == DataUtil.converStr2Int(entity.getProcessResult(), 3)) {

                if (!ObjectUtils.isEmpty(entity.getErrorDateTime()) && !ObjectUtils.isEmpty(entity.getGoOffDateTime())) {

                    Long lateMin = DateUtil.between(entity.getErrorDateTime(), entity.getGoOffDateTime(), DateUnit.MINUTE);
                    if (lateMin >= 0L && lateMin < 5L) {
                        //迟到5分钟内
                        ruleCode = "ATTEND1001";
                    }
                    if (lateMin >= 5L && lateMin < 60L) {
                        //迟到5-60
                        ruleCode = "ATTEND1003";
                    }
                    if (lateMin >= 60L) {
                        //迟到60分钟以上
                        ruleCode = "ATTEND1005";
                    }
                }else{
                    //早退5分钟内
                    ruleCode = "ATTEND1001";
                }
            } else if (ErrorStatusEnum.缺卡.getValue() == DataUtil.converStr2Int(entity.getProcessResult(), 3)) {
                ruleCode = "ATTEND1007";
            }
            if (!ObjectUtils.isEmpty(ruleCode)) {
                AttendSaveReq attendSaveReq = new AttendSaveReq();
                attendSaveReq.setAttendanceGroupId(entity.getAttendanceGroupId());
                attendSaveReq.setAttendanceGroupName(entity.getAttendanceGroupName());
                attendSaveReq.setAttendanceDate(entity.getActualAttendanceDateTime());
                attendSaveReq.setErrorTime(entity.getErrorDateTime());
                attendSaveReq.setGoOffTimeStr(entity.getGoOrOff());
                attendSaveReq.setActualAttendTime(entity.getActualAttendanceDateTime());
                attendSaveReq.setErrorResult(entity.getRemark());

                attendSaveReq.setTitle("考勤");
                attendSaveReq.setHappenTime(entity.getErrorDateTime());
                attendSaveReq.setRuleCode(ruleCode);
                attendSaveReq.setStaffId(entity.getStaffId());
                performAttendRecordService.saveAttend(attendSaveReq, context);
            }
            //异常处理后重新汇总考勤 context!=null时表示页面调用的修改，自动执行处理任务调用时context为null，无需立即汇总
            if(StringUtils.isNotEmpty(entity.getProcessResult())&&context!=null) {
                AttendanceSummaryQuery query = new AttendanceSummaryQuery();
                query.setStaffId(entity.getStaffId());
                query.setSummaryTime(DateUtils.getStrDate(entity.getErrorDateTime()));
//                AttendSummaryThread summaryThread = new AttendSummaryThread(attendanceStatService, query);
//                ThreadPool.getInstance().execute(summaryThread);
                cacheService.lpush(KEY_ATTENDANCE_STAT_CACHE,query);
            }
        }
    }

    @Override
    public boolean errorConfirm(Long errorId) {
        boolean result = true;
        AttendanceRecordErrorEntity errorEntity = this.get(errorId);
        if(errorEntity!=null) {
            AttendanceLeaveRecordQuery query = new AttendanceLeaveRecordQuery();
            query.setEndTimeStart(DateUtils.getStrDate(errorEntity.getErrorDateTime()));
            query.setLeavePersonId(errorEntity.getStaffId());
            query.setAuditResult(AppealResultEnum.通过.getValue());
            AttendanceLeaveRecordEntity leaveRecordEntity = attendanceLeaveRecordService.selectOne(query);
            if(leaveRecordEntity != null){
                result = false;
            }
        }
        return result;
    }

    @Override
    public void doAutoProcess(Date date) {
        AttendanceRecordErrorQuery query = new AttendanceRecordErrorQuery();
        query.setErrorDateTimeStart(DateUtils.getStrDate(date));
        query.setErrorDateTimeEnd(DateUtils.getStrDate(date));
        List<AttendanceRecordErrorEntity> list = this.find(query);
        if(CollectionUtils.isNotEmpty(list)){
            list.stream().forEach(item->{
                if(errorConfirm(item.getId())){
                    AttendanceRecordErrorEntity updateEntity = new AttendanceRecordErrorEntity();
                    updateEntity.setId(item.getId());
                    updateEntity.setProcessStatus(1);
                    updateEntity.setProcessResult(String.valueOf(item.getErrorStatus()));
                    updateEntity.setStaffId(item.getStaffId());
                    updateEntity.setOpertor("系统自动处理");
                    updateEntity.setOperDateTime(new Date());
                    updateEntity.setRemark("系统自动处理");
                    updateEntity.setUpdateTime(new Date());
                    updateEntity.setUpdateUserId(1l);
                    this.update(updateEntity,null);
                }
            });
        }
    }

    @Override
    public void doReprocess(AttendanceRecordErrorQuery query, Context context) {
        List<String> dateList = getDatesBetween(query.getErrorDateTimeStart(), query.getErrorDateTimeEnd());
        for (String day : dateList) {
            query.setErrorDateTimeStart(day);
            query.setErrorDateTimeEnd(day);
            List<AttendanceRecordErrorEntity> list = this.find(query);
            if (CollectionUtils.isNotEmpty(list)) {
                for (AttendanceRecordErrorEntity entity : list) {
                    if (YesNoEnum.YES.getValue() == entity.getProcessStatus()) {
                        //判断后打绩效
                        String ruleCode = "";
                        if (ErrorStatusEnum.早退.getValue() == DataUtil.converStr2Int(entity.getProcessResult(), 3)) {
                            if (!ObjectUtils.isEmpty(entity.getErrorDateTime()) && !ObjectUtils.isEmpty(entity.getGoOffDateTime())) {
                                //判断时间差定义
                                Long earlyMin = DateUtil.between(entity.getErrorDateTime(), entity.getGoOffDateTime(), DateUnit.MINUTE);

                                if (earlyMin >= 0L && earlyMin < 5L) {
                                    //早退5分钟内
                                    ruleCode = "ATTEND1002";
                                }
                                if (earlyMin >= 5L && earlyMin < 60L) {
                                    //早退5分钟内
                                    ruleCode = "ATTEND1004";
                                }
                                if (earlyMin >= 60L) {
                                    //早退5分钟内
                                    ruleCode = "ATTEND1006";
                                }
                            } else {
                                ruleCode = "ATTEND1002";
                            }
                        } else if (ErrorStatusEnum.迟到.getValue() == DataUtil.converStr2Int(entity.getProcessResult(), 3)) {

                            if (!ObjectUtils.isEmpty(entity.getErrorDateTime()) && !ObjectUtils.isEmpty(entity.getGoOffDateTime())) {

                                Long lateMin = DateUtil.between(entity.getErrorDateTime(), entity.getGoOffDateTime(), DateUnit.MINUTE);
                                if (lateMin >= 0L && lateMin < 5L) {
                                    //迟到5分钟内
                                    ruleCode = "ATTEND1001";
                                }
                                if (lateMin >= 5L && lateMin < 60L) {
                                    //迟到5-60
                                    ruleCode = "ATTEND1003";
                                }
                                if (lateMin >= 60L) {
                                    //迟到60分钟以上
                                    ruleCode = "ATTEND1005";
                                }
                            } else {
                                //早退5分钟内
                                ruleCode = "ATTEND1001";
                            }
                        } else if (ErrorStatusEnum.缺卡.getValue() == DataUtil.converStr2Int(entity.getProcessResult(), 3)) {
                            ruleCode = "ATTEND1007";
                        }
                        if (!ObjectUtils.isEmpty(ruleCode)) {
                            AttendSaveReq attendSaveReq = new AttendSaveReq();
                            attendSaveReq.setAttendanceGroupId(entity.getAttendanceGroupId());
                            attendSaveReq.setAttendanceGroupName(entity.getAttendanceGroupName());
                            attendSaveReq.setAttendanceDate(entity.getActualAttendanceDateTime());
                            attendSaveReq.setErrorTime(entity.getErrorDateTime());
                            attendSaveReq.setGoOffTimeStr(entity.getGoOrOff());
                            attendSaveReq.setActualAttendTime(entity.getActualAttendanceDateTime());
                            attendSaveReq.setErrorResult(entity.getRemark());

                            attendSaveReq.setTitle("考勤");
                            attendSaveReq.setHappenTime(entity.getErrorDateTime());
                            attendSaveReq.setRuleCode(ruleCode);
                            attendSaveReq.setStaffId(entity.getStaffId());
                            performAttendRecordService.saveAttend(attendSaveReq, context);
                        }

                    }
                }
            }
        }

    }

    private List<String> getDatesBetween(String startDateStr, String endDateStr) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate startDate = LocalDate.parse(startDateStr, formatter);
        LocalDate endDate = LocalDate.parse(endDateStr, formatter);
        List<String> dates = new ArrayList<>();
        //这里是判断开始日期是否在结束日期之后或者=结束日期
        while (startDate.isBefore(endDate) || startDate.isEqual(endDate)) {
            String add = startDate.format(formatter);
            dates.add(add);
            startDate = startDate.plusDays(1);
        }
        return dates;
    }
}