package com.yida.data.attendance.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.attendance.dto.AddAttendanceReportStrategyDTO;
import com.yida.data.attendance.dto.AddAttendanceRuleTimeDTO;
import com.yida.data.attendance.dto.PageAttendanceRuleDTO;
import com.yida.data.attendance.mapper.AttendanceReportStrategyMapper;
import com.yida.data.attendance.mapper.AttendanceRuleTimeMapper;
import com.yida.data.attendance.service.AttendanceReportPushRecordService;
import com.yida.data.attendance.service.AttendanceReportStrategyService;
import com.yida.data.attendance.service.AttendanceResultService;
import com.yida.data.attendance.service.AttendanceRuleService;
import com.yida.data.attendance.service.AttendanceRuleTimeService;
import com.yida.data.attendance.vo.AttendanceRuleVO;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceReportPushRecord;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceReportStrategy;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRule;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRuleTime;
import com.yida.data.common.core.enums.EnableStatusEnum;
import com.yida.data.common.core.enums.UserTypeEnum;
import com.yida.data.common.core.enums.attendance.AttendanceModeTypeEnum;
import com.yida.data.common.core.enums.attendance.AttendanceReportTypeEnum;
import com.yida.data.common.core.enums.attendance.AttendanceStrategyTypeEnum;
import com.yida.data.common.core.enums.attendance.AttendanceUserTypeEnum;
import com.yida.data.common.core.utils.FebsUtil;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

/**
 * 考勤-推送策略 Service实现
 *
 * @date 2023-08-09 11:37:25
 */
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
@Slf4j
public class AttendanceReportStrategyServiceImpl extends ServiceImpl
    <AttendanceReportStrategyMapper, AttendanceReportStrategy> implements AttendanceReportStrategyService {

    private final AttendanceRuleService attendanceRuleService;
    private final AttendanceResultService attendanceResultService;
    private final AttendanceReportPushRecordService attendanceReportPushRecordService;

    @Override
    public void saveStrategy(List<AddAttendanceReportStrategyDTO> dtoList) {
        for (AddAttendanceReportStrategyDTO dto : dtoList) {
            AttendanceReportStrategy attendanceReportStrategy = new AttendanceReportStrategy();
            BeanUtils.copyProperties(dto, attendanceReportStrategy);
            saveOrUpdate(attendanceReportStrategy);
        }
    }

    @Override
    public List<AttendanceReportStrategy> getList() {
        List<AttendanceReportStrategy> list = list(Wrappers.lambdaQuery(new AttendanceReportStrategy())
            .eq(AttendanceReportStrategy::getSchoolId, FebsUtil.getTopDeptId()));
        if (CollUtil.isEmpty(list)) {
            AttendanceReportStrategy attendanceReportStrategy = new AttendanceReportStrategy();
            attendanceReportStrategy.setType(0);
            attendanceReportStrategy.setSchoolId(FebsUtil.getTopDeptId());
            save(attendanceReportStrategy);
            AttendanceReportStrategy attendanceReportStrategyStu = new AttendanceReportStrategy();
            attendanceReportStrategyStu.setType(1);
            attendanceReportStrategyStu.setSchoolId(FebsUtil.getTopDeptId());
            save(attendanceReportStrategyStu);
            AttendanceReportStrategy attendanceReportStrategyPar = new AttendanceReportStrategy();
            attendanceReportStrategyPar.setType(2);
            attendanceReportStrategyPar.setSchoolId(FebsUtil.getTopDeptId());
            save(attendanceReportStrategyPar);
            list.add(attendanceReportStrategy);
            list.add(attendanceReportStrategyStu);
            list.add(attendanceReportStrategyPar);
        }
        return list;
    }

    @Override
    public void sendNotice() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        //查询具有考勤规则的学校
        PageAttendanceRuleDTO dto = new PageAttendanceRuleDTO();
        dto.setStatus(EnableStatusEnum.ENABLE_STATUS.getStatus());
        List<AttendanceRuleVO> ruleVOList = attendanceRuleService.listRule(dto);
        //循环规则
        for (AttendanceRuleVO attendanceRuleVO : ruleVOList) {
            //判断规则今日是否有效
            if (LocalDate.now().isBefore(attendanceRuleVO.getStartDate()) || LocalDate.now()
                .isAfter(attendanceRuleVO.getEndDate()) || !attendanceRuleVO.getWeek()
                .contains(String.valueOf(LocalDate.now().getDayOfWeek().getValue()))) {
                continue;
            }
//            log.info("处理【{}】学校，规则【{}】的考勤推送消息", attendanceRuleVO.getSchoolId(), attendanceRuleVO.getName());
            if (ObjectUtil.equals(AttendanceUserTypeEnum.STAFF.getValue(), attendanceRuleVO.getUserType())) {
                //教职工考勤
                //1：职工考勤推送
                AttendanceReportStrategy staffStrategy = getOne(Wrappers.lambdaQuery(new AttendanceReportStrategy())
                    .eq(AttendanceReportStrategy::getSchoolId, attendanceRuleVO.getSchoolId())
                    .eq(AttendanceReportStrategy::getType, AttendanceStrategyTypeEnum.STAFF_STAFF.getValue()));

                //日报
                if (ObjectUtil.equals(EnableStatusEnum.ENABLE_STATUS.getStatus(), staffStrategy.getDayReport())) {
                    //TODO 发送管理员职工日报
                    List<AddAttendanceRuleTimeDTO> timeDTOList = attendanceRuleVO.getTimeDTOList();
                    List<AddAttendanceRuleTimeDTO> ruleTimeDTOList = timeDTOList.stream()
                        .sorted(Comparator.comparing(AddAttendanceRuleTimeDTO::getEndTime).reversed())
                        .collect(Collectors.toList());
                    LocalTime endTime = ruleTimeDTOList.get(0).getEndTime();
                    if (LocalTime.now().isAfter(endTime.plusMinutes(staffStrategy.getDayReportTime()))) {
                        //判断是否已发布
                        AttendanceReportPushRecord reportPushRecord = attendanceReportPushRecordService
                            .getOne(Wrappers.lambdaQuery(new AttendanceReportPushRecord())
                                .eq(AttendanceReportPushRecord::getPushDate, LocalDate.now())
                                .eq(AttendanceReportPushRecord::getReportType, AttendanceReportTypeEnum.DAY_REPORT.getValue())
                                .eq(AttendanceReportPushRecord::getSchoolId, attendanceRuleVO.getSchoolId())
                                .eq(AttendanceReportPushRecord::getRuleId, attendanceRuleVO.getId())
                                .eq(AttendanceReportPushRecord::getType, UserTypeEnum.STAFF_USER_TYPE.getType()));

                        if (ObjectUtil.isNull(reportPushRecord)) {
                            //大于结束时间10分钟
                            attendanceResultService
                                .dayReport(0, UserTypeEnum.STAFF_USER_TYPE.getType(), attendanceRuleVO.getId());
                            //增加推送记录
                            AttendanceReportPushRecord pushRecord = new AttendanceReportPushRecord();
                            pushRecord.setPushDate(LocalDate.now());
                            pushRecord.setSchoolId(attendanceRuleVO.getSchoolId());
                            pushRecord.setRuleId(attendanceRuleVO.getId());
                            pushRecord.setReportType(AttendanceReportTypeEnum.DAY_REPORT.getValue());
                            pushRecord.setType(UserTypeEnum.STAFF_USER_TYPE.getType());
                            attendanceReportPushRecordService.save(pushRecord);
                        }
                    }
                }

                //周报
                if (ObjectUtil.equals(EnableStatusEnum.ENABLE_STATUS.getStatus(), staffStrategy.getWeekReport()) &&
                    ObjectUtil.equals(staffStrategy.getWeekReportDate(), LocalDate.now().getDayOfWeek().getValue()) &&
                    staffStrategy.getWeekReportTime().isAfter(LocalTime.now())) {

                    //TODO 发送管理员职工周报

                }
                //月报
                if (ObjectUtil.equals(EnableStatusEnum.ENABLE_STATUS.getStatus(), staffStrategy.getMonthReport())) {
                    if (ObjectUtil.equals(staffStrategy.getMonthReportDate(), LocalDate.now().getDayOfMonth())) {
                        if (staffStrategy.getMonthReportTime().isAfter(LocalTime.now())) {
                            //TODO 发送管理员职工月报
                        }
                    }
                }
                //迟到提醒
                if (ObjectUtil.equals(EnableStatusEnum.ENABLE_STATUS.getStatus(), staffStrategy.getLateReport())) {
                    if (ObjectUtil.equals(AttendanceModeTypeEnum.FREE.getValue(), attendanceRuleVO.getType())) {
                        //固定打卡模式
                        List<AddAttendanceRuleTimeDTO> timeDTOList = attendanceRuleVO.getTimeDTOList();
                        if (CollUtil.isNotEmpty(timeDTOList)) {
                            for (AddAttendanceRuleTimeDTO ruleTimeDTO : timeDTOList) {
                                if (LocalTime.now()
                                    .isAfter(ruleTimeDTO.getStartTime().plusMinutes(staffStrategy.getLateReportTime()))) {
                                    //TODO 发送职工迟到提醒
                                }
                            }
                        }
                    }
                }

                //缺卡提醒
                if (ObjectUtil.equals(EnableStatusEnum.ENABLE_STATUS.getStatus(), staffStrategy.getMissReport())) {
                    //固定打卡模式
                    List<AddAttendanceRuleTimeDTO> timeDTOList = attendanceRuleVO.getTimeDTOList();
                    if (CollUtil.isNotEmpty(timeDTOList)) {
                        for (AddAttendanceRuleTimeDTO ruleTimeDTO : timeDTOList) {
                            if (LocalTime.now()
                                .isAfter(ruleTimeDTO.getEndTime().plusMinutes(staffStrategy.getMissReportTime()))) {
                                //TODO 发送职工缺卡提醒
                            }
                        }
                    }
                }
            } else {
                //学生考勤
                //1：学生考勤推送
                AttendanceReportStrategy staffStrategy = getOne(Wrappers.lambdaQuery(new AttendanceReportStrategy())
                    .eq(AttendanceReportStrategy::getSchoolId, attendanceRuleVO.getSchoolId())
                    .eq(AttendanceReportStrategy::getType, AttendanceStrategyTypeEnum.STUDENT_STAFF.getValue()));
                List<Long> staffList = new ArrayList<>();
                if (ObjectUtil.isNotNull(staffStrategy.getObjStaffIds())) {
                    staffList = Arrays.stream(staffStrategy.getObjStaffIds().split(","))
                        .map(s -> Long.parseLong(s.trim()))
                        .collect(Collectors.toList());
                }

                //日报
                if (ObjectUtil.equals(EnableStatusEnum.ENABLE_STATUS.getStatus(), staffStrategy.getDayReport())) {
                    //TODO 发送管理员职工日报
                    List<AddAttendanceRuleTimeDTO> timeDTOList = attendanceRuleVO.getTimeDTOList();
                    List<AddAttendanceRuleTimeDTO> ruleTimeDTOList = timeDTOList.stream()
                        .sorted(Comparator.comparing(AddAttendanceRuleTimeDTO::getEndTime).reversed())
                        .collect(Collectors.toList());
                    LocalTime endTime = ruleTimeDTOList.get(0).getEndTime();
                    if (LocalTime.now().isAfter(endTime.plusMinutes(staffStrategy.getDayReportTime()))) {

                        //判断是否已发布
                        AttendanceReportPushRecord reportPushRecord = attendanceReportPushRecordService
                            .getOne(Wrappers.lambdaQuery(new AttendanceReportPushRecord())
                                .eq(AttendanceReportPushRecord::getPushDate, LocalDate.now())
                                .eq(AttendanceReportPushRecord::getReportType, AttendanceReportTypeEnum.DAY_REPORT.getValue())
                                .eq(AttendanceReportPushRecord::getSchoolId, attendanceRuleVO.getSchoolId())
                                .eq(AttendanceReportPushRecord::getRuleId, attendanceRuleVO.getId())
                                .eq(AttendanceReportPushRecord::getType, UserTypeEnum.PARENT_USER_TYPE.getType()));

                        if (ObjectUtil.isNull(reportPushRecord)) {
                            //大于结束时间10分钟
                            attendanceResultService
                                .dayReport(0, UserTypeEnum.PARENT_USER_TYPE.getType(), attendanceRuleVO.getId());
                            //增加推送记录
                            AttendanceReportPushRecord pushRecord = new AttendanceReportPushRecord();
                            pushRecord.setPushDate(LocalDate.now());
                            pushRecord.setSchoolId(attendanceRuleVO.getSchoolId());
                            pushRecord.setRuleId(attendanceRuleVO.getId());
                            pushRecord.setReportType(AttendanceReportTypeEnum.DAY_REPORT.getValue());
                            pushRecord.setType(UserTypeEnum.PARENT_USER_TYPE.getType());
                            attendanceReportPushRecordService.save(pushRecord);
                        }
                    }
                }
                //周报
                if (ObjectUtil.equals(EnableStatusEnum.ENABLE_STATUS.getStatus(), staffStrategy.getWeekReport())
                    && ObjectUtil.equals(staffStrategy.getWeekReportDate(), LocalDate.now().getDayOfWeek().getValue())
                    && staffStrategy.getWeekReportTime().isAfter(LocalTime.now())) {
                    //TODO 发送管理员学生周报

                }
                //月报
                if (ObjectUtil.equals(EnableStatusEnum.ENABLE_STATUS.getStatus(), staffStrategy.getMonthReport()) &&
                    ObjectUtil.equals(staffStrategy.getMonthReportDate(), LocalDate.now().getDayOfMonth()) &&
                    staffStrategy.getMonthReportTime().isAfter(LocalTime.now())) {
                    //TODO 发送管理员学生月报

                }
                //迟到提醒
                if (ObjectUtil.equals(EnableStatusEnum.ENABLE_STATUS.getStatus(), staffStrategy.getLateReport())) {
                    List<AddAttendanceRuleTimeDTO> timeDTOList = attendanceRuleVO.getTimeDTOList();
                    if (CollUtil.isNotEmpty(timeDTOList)) {
                        for (AddAttendanceRuleTimeDTO ruleTimeDTO : timeDTOList) {
                            if (ObjectUtil
                                .equals(AttendanceUserTypeEnum.STUDENT_TO_DORM.getValue(), attendanceRuleVO.getUserType())) {
                                //宿舍考勤
                                if (LocalTime.now()
                                    .isAfter(ruleTimeDTO.getEndTime().plusMinutes(staffStrategy.getLateReportTime()))) {
                                    //TODO 发送职工学生提醒
                                    attendanceResultService
                                        .lateReport(0, 1, attendanceRuleVO.getId(), ruleTimeDTO.getId(), staffList,
                                            staffStrategy.getObjManager());
                                }
                            } else {
                                if (LocalTime.now()
                                    .isAfter(ruleTimeDTO.getStartTime().plusMinutes(staffStrategy.getLateReportTime()))) {
                                    //TODO 发送职工学生提醒
                                    attendanceResultService
                                        .lateReport(0, 1, attendanceRuleVO.getId(), ruleTimeDTO.getId(), staffList,
                                            staffStrategy.getObjManager());
                                }
                            }
                        }
                    }
                }

                //缺卡提醒
                if (ObjectUtil.equals(EnableStatusEnum.ENABLE_STATUS.getStatus(), staffStrategy.getMissReport())) {
                    List<AddAttendanceRuleTimeDTO> timeDTOList = attendanceRuleVO.getTimeDTOList();
                    if (CollUtil.isNotEmpty(timeDTOList)) {
                        for (AddAttendanceRuleTimeDTO ruleTimeDTO : timeDTOList) {
                            if (LocalTime.now()
                                .isAfter(ruleTimeDTO.getEndEffectiveEndTime().plusMinutes(staffStrategy.getMissReportTime()))) {
                                //TODO 发送职工学生提醒

                            }
                        }
                    }
                }

                //家长提醒
                AttendanceReportStrategy staffStrategyParent = getOne(Wrappers.lambdaQuery(new AttendanceReportStrategy())
                    .eq(AttendanceReportStrategy::getSchoolId, attendanceRuleVO.getSchoolId())
                    .eq(AttendanceReportStrategy::getType, AttendanceStrategyTypeEnum.STUDENT_PARENT.getValue()));

                //迟到提醒
                if (ObjectUtil.equals(1, staffStrategyParent.getLateReport())) {
                    if (ObjectUtil.equals(AttendanceModeTypeEnum.FREE.getValue(), attendanceRuleVO.getType())) {
                        //固定打卡模式
                        List<AddAttendanceRuleTimeDTO> timeDTOList = attendanceRuleVO.getTimeDTOList();
                        if (CollUtil.isNotEmpty(timeDTOList)) {
                            for (AddAttendanceRuleTimeDTO ruleTimeDTO : timeDTOList) {
                                if (LocalTime.now()
                                    .isAfter(ruleTimeDTO.getStartTime().plusMinutes(staffStrategy.getLateReportTime()))) {
                                    //TODO 发送家长学生提醒
                                }
                            }
                        }
                    }
                }

                //缺卡提醒
                if (ObjectUtil.equals(1, staffStrategyParent.getMissReport())) {
                    List<AddAttendanceRuleTimeDTO> timeDTOList = attendanceRuleVO.getTimeDTOList();
                    if (CollUtil.isNotEmpty(timeDTOList)) {
                        for (AddAttendanceRuleTimeDTO ruleTimeDTO : timeDTOList) {
                            if (LocalTime.now()
                                .isAfter(ruleTimeDTO.getEndTime().plusMinutes(staffStrategy.getMissReportTime()))) {
                                //TODO 发送家长学生提醒
                            }
                        }
                    }
                }

            }
        }

        stopWatch.stop();
        log.info("推送报告结束，总共耗时：[{}]", stopWatch.getTotalTimeSeconds() + "秒");
    }
}
