package com.xjrsoft.module.job;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xjrsoft.XjrSoftApplication;
import com.xjrsoft.common.enums.OutInStatusEnum;
import com.xjrsoft.common.utils.VoToColumnUtil;
import com.xjrsoft.module.attendance.entity.AttendanceRuleDetails;
import com.xjrsoft.module.attendance.entity.TeacherAttendanceRecord;
import com.xjrsoft.module.attendance.service.IAttendanceRuleCategoryService;
import com.xjrsoft.module.attendance.service.ITeacherAttendanceRecordService;
import com.xjrsoft.module.attendance.vo.AttendanceRuleDetailsUserVo;
import com.xjrsoft.module.holiday.entity.HolidayDate;
import com.xjrsoft.module.holiday.service.IHolidayDateService;
import com.xjrsoft.module.organization.entity.User;
import com.xjrsoft.module.organization.service.IUserService;
import com.xjrsoft.module.outint.dto.TeacherOutInRecordDto;
import com.xjrsoft.module.outint.entity.CarOutInRecord;
import com.xjrsoft.module.outint.entity.TeacherOutInRecord;
import com.xjrsoft.module.outint.service.ICarOutInRecordService;
import com.xjrsoft.module.outint.service.ITeacherOutInRecordService;
import com.xjrsoft.module.personnel.entity.CarMessageApply;
import com.xjrsoft.module.teacher.entity.BaseTeacher;
import com.xjrsoft.module.teacher.entity.WfHeadTeacherLeave;
import com.xjrsoft.module.teacher.entity.WfTeacherleave;
import com.xjrsoft.module.teacher.entity.XjrUser;
import com.xjrsoft.module.teacher.service.IWfHeadTeacherLeaveService;
import com.xjrsoft.module.teacher.service.IWfTeacherleaveService;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author dzx
 * @date 2024/10/19
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = XjrSoftApplication.class)
class AttendanceRecordTaskTest {

    @Autowired
    private IUserService userService;

    @Autowired
    private IAttendanceRuleCategoryService ruleCategoryService;

    @Autowired
    private IWfTeacherleaveService wfTeacherleaveService;

    @Autowired
    private IWfHeadTeacherLeaveService headTeacherLeaveService;

    @Autowired
    private ITeacherOutInRecordService teacherOutInRecordService;

    @Autowired
    private ICarOutInRecordService carOutInRecordService;

    @Autowired
    private ITeacherAttendanceRecordService recordService;

    @Autowired
    private IHolidayDateService holidayDateService;
    @Test
    public void execute() {

        LocalDateTime now = LocalDateTime.of(2024, 10, 1, 0, 0, 0);
        for (int i = 0; i < 21; i ++){
            LocalDateTime startDateTime = now.plusDays(i).withHour(0).withMinute(0).withSecond(0).withNano(0);
            LocalDateTime endDateTime = startDateTime.plusDays(i).withHour(23).withMinute(59).withSecond(59);

            teacherAttendanceRecord(startDateTime, endDateTime, 1);

            teacherAttendanceRecord(startDateTime, endDateTime, 2);
        }

    }

    /**
     * 根据时间段，统计这个时间段内的考勤数据
     * @param startDateTime 开始时间
     * @param endDateTime 结束时间
     */
    public void teacherAttendanceRecord(LocalDateTime startDateTime, LocalDateTime endDateTime, Integer timePeriod){
        List<User> teacherList = userService.list(
                new MPJLambdaWrapper<User>()
                        .select(User::getId)
                        .select(User.class, x -> VoToColumnUtil.fieldsToColumns(User.class).contains(x.getProperty()))
                        .innerJoin(BaseTeacher.class, BaseTeacher::getUserId, User::getId)
        );
        List<Long> userIds = teacherList.stream().map(User::getId).collect(Collectors.toList());
        Map<Long, AttendanceRuleDetailsUserVo> teacherTodyRuleByUserId = ruleCategoryService.getTeacherTodyRuleByUserId(userIds);

        List<Integer> holidayTypes = Arrays.asList(1, 3);
        List<HolidayDate> holidayDates = holidayDateService.list(
                new QueryWrapper<HolidayDate>().lambda()
                        .in(HolidayDate::getStatus, holidayTypes)
        );
        List<String> holidayDateList = holidayDates.stream().map(HolidayDate::getDate).collect(Collectors.toList());
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate queryDate = startDateTime.toLocalDate();
        List<TeacherAttendanceRecord> insertList = new ArrayList<>();
        List<String> weekList =Arrays.asList("SUNDAY", "SATURDAY");

        List<HolidayDate> workHolidayDates = holidayDateService.list(
                new QueryWrapper<HolidayDate>().lambda()
                        .eq(HolidayDate::getStatus, 2)
        );
        List<String> workHolidayDateListg = workHolidayDates.stream().map(HolidayDate::getDate).collect(Collectors.toList());

        for (User user : teacherList) {
            TeacherAttendanceRecord record = new TeacherAttendanceRecord();
            record.setCreateDate(LocalDateTime.now());
            record.setAttendanceDate(queryDate);
            record.setUserId(user.getId());
            record.setTimeInterval(timePeriod);
            AttendanceRuleDetailsUserVo detailsUserVo = teacherTodyRuleByUserId.get(user.getId());

            if(detailsUserVo == null){
                record.setAttendanceStatus("不考勤");
                insertList.add(record);
                continue;
            }
            AttendanceRuleDetails holidayRule = ruleCategoryService.getHolidayRuleByParam(user.getId());
            if(((!workHolidayDateListg.contains(queryDate.format(formatter)) && weekList.contains(queryDate.getDayOfWeek().name()))
                    || holidayDateList.contains(queryDate.format(formatter))) && (holidayRule.getIsAttendance() == null || holidayRule.getIsAttendance() == 0)){
                record.setAttendanceStatus("不考勤");
                insertList.add(record);
                continue;
            }

            LocalDateTime startTime, endTime, amEndTime = null;

            if(timePeriod == 1){
                startTime = queryDate.atTime(5, 0, 0);
                if(detailsUserVo.getAmStartTime() != null){
                    startTime = queryDate.atTime(detailsUserVo.getAmStartTime());
                }
                endTime = queryDate.atTime(12, 0, 0);
                if(detailsUserVo.getAmEndTime() != null){
                    endTime = queryDate.atTime(detailsUserVo.getAmEndTime());
                }
            }else if(timePeriod == 2){
                startTime = queryDate.atTime(12, 0, 0);
                if(detailsUserVo.getPmStartTime() != null){
                    startTime = queryDate.atTime(detailsUserVo.getPmStartTime());
                }
                endTime = queryDate.atTime(18, 0, 0);
                if(detailsUserVo.getPmEndTime() != null){
                    endTime = queryDate.atTime(detailsUserVo.getPmEndTime());
                }
                amEndTime  = queryDate.atTime(12, 0, 0);
                if(detailsUserVo.getAmEndTime() != null){
                    amEndTime = queryDate.atTime(detailsUserVo.getAmEndTime());
                }
            }else{
                startTime = queryDate.atTime(0, 0, 0);
                if(detailsUserVo.getEveningStartTime() != null){
                    startTime = queryDate.atTime(detailsUserVo.getEveningStartTime());
                }
                endTime = queryDate.atTime(23, 59, 59);
                if(detailsUserVo.getEveningEndTime() != null){
                    endTime = queryDate.atTime(detailsUserVo.getEveningEndTime());
                }
            }
            record.setStartTime(startTime);
            record.setEndTime(endTime);

            WfTeacherleave studentLeave = wfTeacherleaveService.getLeaveByUserId(startTime, endTime, user.getId());
            if(studentLeave != null){
                record.setAttendanceStatus(studentLeave.getLeaveType());
                continue;
            }

            WfHeadTeacherLeave teacherLeave = headTeacherLeaveService.selectJoinOne(WfHeadTeacherLeave.class,
                    new MPJLambdaWrapper<WfHeadTeacherLeave>()
                            .select(WfHeadTeacherLeave.class, x -> VoToColumnUtil.fieldsToColumns(WfHeadTeacherLeave.class).contains(x.getProperty()))
                            .innerJoin(XjrUser.class, XjrUser::getId, WfHeadTeacherLeave::getApplicantUserId)
                            .eq(WfHeadTeacherLeave::getStatus, 1)
                            .eq(WfHeadTeacherLeave::getApplicantUserId, record.getUserId())
                            .between(WfHeadTeacherLeave::getStartTime, startTime, endTime)
            );
            if(teacherLeave != null){
                record.setAttendanceStatus(teacherLeave.getLeaveReason());
                continue;
            }
            TeacherOutInRecordDto outInDto = new TeacherOutInRecordDto();
            outInDto.setQueryDate(startTime.toLocalDate());
            outInDto.setEndTime(endTime);
            outInDto.setStartTime(startTime);
            outInDto.setStatus(OutInStatusEnum.enter.getCode());
            outInDto.setUserId(record.getUserId());
            List<TeacherOutInRecord> outInRecords = teacherOutInRecordService.getListByParam(outInDto);
            if(!outInRecords.isEmpty()){
                TeacherOutInRecord outInRecord = outInRecords.get(0);
                if(outInRecord != null){
                    record.setRecordTime(outInRecord.getRecordTime());
                    record.setAttendanceStatus(outInRecord.getAttendanceStatus());
                    record.setAttendanceMode(1);
                }
            }else{
                //查询该教师是否通过车辆进入
                List<CarOutInRecord> list = carOutInRecordService.list(
                        new MPJLambdaWrapper<CarOutInRecord>()
                                .select(CarOutInRecord.class, x -> VoToColumnUtil.fieldsToColumns(CarOutInRecord.class).contains(x.getProperty()))
                                .leftJoin(CarMessageApply.class, CarMessageApply::getId, CarOutInRecord::getCarMessageApplyId)
                                .le(CarOutInRecord::getRecordTime, endTime)
                                .eq("DATE_FORMAT(record_time, '%Y-%m-%d')", endTime.toLocalDate())
                                .eq(CarMessageApply::getUserId, record.getUserId())
                                .ge(timePeriod != null && timePeriod == 2 && amEndTime != null, CarOutInRecord::getRecordTime, amEndTime)
                                .eq(CarOutInRecord::getStatus, OutInStatusEnum.enter.getCode())
                                .orderByAsc(CarOutInRecord::getRecordTime)
                );
                if(!list.isEmpty()){
                    CarOutInRecord outInRecord = list.get(0);
                    if(outInRecord != null && outInRecord.getRecordTime().isBefore(startTime)){
                        record.setRecordTime(outInRecord.getRecordTime());
                        record.setAttendanceStatus("到校");
                        record.setAttendanceMode(2);
                        record.setCarNumber(outInRecord.getPlanNo());
                    }else if(outInRecord != null && outInRecord.getRecordTime().isAfter(startTime)){
                        record.setRecordTime(outInRecord.getRecordTime());
                        record.setAttendanceStatus("迟到");
                        record.setAttendanceMode(1);
                        record.setCarNumber(outInRecord.getPlanNo());
                    }
                }
            }

            if(record.getAttendanceStatus() == null){
                record.setAttendanceStatus("缺勤");
            }

            insertList.add(record);
        }

        if(!insertList.isEmpty()){
            recordService.saveBatch(insertList);
        }
    }
}