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


import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.attendance.dto.AttendanceResultPageDTO;
import com.yida.data.attendance.dto.ListStudentResultDTO;
import com.yida.data.attendance.mapper.EduAttendanceRecordMapper;
import com.yida.data.attendance.mapper.EduAttendanceResultMapper;
import com.yida.data.attendance.mapper.EduAttendanceVerifyDormMapper;
import com.yida.data.attendance.service.EduAttendanceConfigService;
import com.yida.data.attendance.service.EduAttendanceManagePushResultService;
import com.yida.data.attendance.service.EduAttendanceResultService;
import com.yida.data.attendance.service.GenerateAttendanceResultService;
import com.yida.data.attendance.vo.*;
import com.yida.data.common.core.entity.attendance.*;
import com.yida.data.common.core.entity.constant.AppConstant;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.constant.StringConstant;
import com.yida.data.common.core.entity.notice.qywx.NewsStaffNotice;
import com.yida.data.common.core.entity.notice.qywx.TextSchoolNotice;
import com.yida.data.common.core.entity.notice.qywx.inside.Article;
import com.yida.data.common.core.entity.notice.qywx.inside.News;
import com.yida.data.common.core.entity.notice.qywx.inside.Text;
import com.yida.data.common.core.entity.school.EduDormitory;
import com.yida.data.common.core.entity.school.EduDormitoryRoom;
import com.yida.data.common.core.entity.system.EduApp;
import com.yida.data.common.core.entity.user.EduParent;
import com.yida.data.common.core.entity.user.EduStaff;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.enums.AttendanceResult;
import com.yida.data.common.core.utils.EnumUtils;
import com.yida.data.common.core.utils.ExcelUtil;
import com.yida.data.common.core.utils.WxUtil;
import com.yida.data.common.service.CommonService;
import com.yida.data.school.dto.index.ListDormRoomDTO;
import com.yida.data.school.feign.facility.RemoteDormitoryService;
import com.yida.data.user.dto.ListStudentDTO;
import com.yida.data.user.dto.ListStudentDTO.ListStudentDTOBuilder;
import com.yida.data.user.feign.RemoteStaffService;
import com.yida.data.user.feign.RemoteStudentService;
import com.yida.data.user.feign.RemoteTeacherService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 考勤结果 Service实现
 *
 * @author wjm
 * @date 2021-09-15 09:56:24
 */
@Slf4j
@Service
@RequiredArgsConstructor
@RefreshScope
public class EduAttendanceResultServiceImpl extends ServiceImpl<EduAttendanceResultMapper, EduAttendanceResult>
    implements EduAttendanceResultService {

    private static final String NOTICE_URL = "/attendance/url";
    private static final String MANAGE_NOTICE_URL = "/attendance/teacher/result";
    private final EduAttendanceConfigService eduAttendanceConfigService;
    private final EduAttendanceManagePushResultService eduAttendanceManagePushResultService;

    private final EduAttendanceRecordMapper eduAttendanceRecordMapper;
    private final EduAttendanceVerifyDormMapper eduAttendanceVerifyDormMapper;

    private final RemoteDormitoryService remoteDormitoryService;
    private final RemoteStudentService remoteStudentService;
    private final RemoteStaffService remoteStaffService;
    private final RemoteTeacherService remoteTeacherService;

    private final RedisService redisService;
    private final CommonService commonService;
    private final WxUtil wxUtil;
    private final GenerateAttendanceResultService generateAttendanceResultService;
    @Value("${febs.pageUrl}")
    private String pageUrl;

    @Override
    @Transactional
    public List<StayStudentResultVO> listResultByDorm(Long dormId, String date, Integer time, String keyword, Integer status) {
        List<StayStudentResultVO> resList = new ArrayList<>();
        List<EduDormitoryRoom> roomList =
            remoteDormitoryService.listDormRoom(ListDormRoomDTO.builder().dormIds(Collections.singletonList(dormId)).build())
                .getData();
        if (CollUtil.isNotEmpty(roomList)) {
            List<Long> roomIds = roomList.stream().map(EduDormitoryRoom::getId).collect(Collectors.toList());
            // 查询所有寝室的考勤记录
            List<EduAttendanceResult> resultList = baseMapper
                .listStudentResult(roomIds, null, LocalDateTimeUtil.parseDate(date, DateTimeFormatter.ISO_DATE),
                    null, null, null, null, null, time, 1, status);
            List<Long> studentIds = resultList.stream().map(EduAttendanceResult::getStudentId).distinct()
                .collect(Collectors.toList());
            // 查询考勤记录的学生
            List<EduStudent> studentList = remoteStudentService
                .listStudent(ListStudentDTO.builder().studentIds(studentIds).isQuerySchoolName(false).isQueryParent(false)
                    .isQueryUserDept(false).build()).getData();
            Map<Long, List<EduStudent>> studentGroup = studentList.stream().collect(Collectors.groupingBy(EduStudent::getId));
            Map<Long, List<EduDormitoryRoom>> roomGroup = roomList.stream()
                .collect(Collectors.groupingBy(EduDormitoryRoom::getId));
            for (EduAttendanceResult result : resultList) {
                if (studentGroup.containsKey(result.getStudentId())) {
                    List<EduStudent> student = studentGroup.get(result.getStudentId());
                    StayStudentResultVO res = new StayStudentResultVO();
                    res.setStudentName(student.get(0).getStuName());
                    res.setStudentId(result.getStudentId());
                    res.setDormRoomName(roomGroup.get(result.getDormRoomId()).get(0).getName());
                    res.setTime(result.getInTime());
                    res.setResult(translateResult(result.getStatus()));
                    if (StrUtil.isNotBlank(keyword)) {
                        if (!(res.getStudentName() + res.getDormRoomName()).contains(keyword)) {
                            continue;
                        }
                    }
                    resList.add(res);
                }
            }
        }
        return resList;
    }

    @Override
    @Transactional
    public List<StayStudentResultVO> listStudentResByDormRoom(Long roomId, String date, Integer time) {
        List<StayStudentResultVO> resList = new ArrayList<>();
        // 查询考勤记录的学生
        List<EduStudent> studentList = remoteStudentService.listStudent(
            ListStudentDTO.builder().dormRoomIds(Collections.singletonList(roomId)).isQueryUserDept(false).isQueryParent(false)
                .isQuerySchoolName(false).build())
            .getData();
        LocalDate day = LocalDate.parse(date);
        LocalDateTime startTime = day.atStartOfDay();
        LocalDateTime endTime = day.atTime(23, 59, 59);
        // 循环每个学生
        for (EduStudent student : studentList) {
            StayStudentResultVO res = new StayStudentResultVO();
            res.setAvatar(student.getAvatar());
            res.setStudentNumber(student.getStuNumber());
            res.setStudentName(student.getStuName());
            res.setStudentId(student.getId());
            EduAttendanceRecord lastRecord = eduAttendanceRecordMapper
                .getLastRecordByTime(startTime, endTime, null, student.getId());
            // 学生有在寝的记录
            if (lastRecord == null || lastRecord.getScope() == 1) {
                res.setStatus(1);
            } else {
                res.setStatus(0);
            }
            resList.add(res);
        }
        return resList;
    }

    @Override
    @Transactional
    public void changeStayStudentStatus(Long studentId, String date, Integer time, Integer status) {
        EduStudent student = (EduStudent) redisService.hget(CachePrefixConstant.STUDENT_DATA, studentId.toString());
        if (student == null) {
            student = remoteStudentService.getStudentNoPermission(studentId).getData();
        }
        EduAttendanceRecord record = new EduAttendanceRecord();
        record.setSchoolId(student.getSchoolId());
        record.setCampusId(student.getCampusId());
        record.setGradeId(student.getGradeId());
        record.setGradeName(student.getGradeName());
        record.setClassId(student.getClassId());
        record.setClassName(student.getClassName());
        record.setStudentId(studentId);
        record.setStatus(-1);
        record.setCreateTime(LocalDateTime.now());
        record.setDormId(student.getDormId());
        record.setDormRoomId(student.getDormRoomId());
        record.setZone(1);
        if (status == 0) {
            record.setScope(0);
        } else {
            record.setScope(1);
        }
        eduAttendanceRecordMapper.insert(record);
    }

    @Override
    @Transactional
    public void verifyDormRoom(EduAttendanceVerifyDorm verifyDorm) {
        eduAttendanceVerifyDormMapper.insert(verifyDorm);
    }

    @Override
    @Transactional
    public IPage<AttendanceResultDormVO> listAttendanceResultPage(AttendanceResultPageDTO dto) {

        // 获取学生
        List<Long> studentIds = null;
        ListStudentDTO listStudentDTO = ListStudentDTO.builder().isQueryParent(false).isQuerySchoolName(false).build();
        BeanUtils.copyProperties(dto, listStudentDTO);
        if (dto.getType() == 0) {
            //查询全部学生
            listStudentDTO.setType(null);
        } else {
            //查询住宿生
            listStudentDTO.setType(1);
        }

        // 筛选寝室
        List<Long> roomList = new ArrayList<>();
        if (dto.getDormRoomId() != null) {
            roomList.add(dto.getDormRoomId());
        } else if (dto.getDormId() != null) {
            List<EduDormitoryRoom> data = remoteDormitoryService
                .listDormRoom(ListDormRoomDTO.builder().dormIds(Collections.singletonList(dto.getDormId())).build()).getData();
            if (CollUtil.isNotEmpty(data)) {
                roomList = data.stream().map(EduDormitoryRoom::getId).collect(Collectors.toList());
            }
        }
        listStudentDTO.setDormRoomIds(roomList);

        // 查询匹配的学生
        List<EduStudent> studentList = remoteStudentService.listStudent(listStudentDTO).getData();

        if (CollUtil.isNotEmpty(studentList)) {
            if (StrUtil.isNotBlank(dto.getKeyword())) {
                studentList = studentList.stream()
                    .filter(x -> x.getStuName().contains(dto.getKeyword()) || x.getStuNumber().contains(dto.getKeyword()))
                    .collect(Collectors.toList());
            }
            if (CollUtil.isNotEmpty(studentList)) {
                studentIds = studentList.stream().map(EduStudent::getId).collect(Collectors.toList());
            }
        }
        // 查询考勤结果记录
        Page<AttendanceResultDormVO> recordPage = Page.of(dto.getPageNum(), dto.getPageSize());
        recordPage.setRecords(
            baseMapper.listAttendanceResult(recordPage, studentIds, dto.getRuleId(), dto.getStartDate(), dto.getEndDate()));
        if (CollUtil.isNotEmpty(recordPage.getRecords()) && CollUtil.isNotEmpty(studentList)) {
            for (AttendanceResultDormVO record : recordPage.getRecords()) {
                for (EduStudent student : studentList) {
                    if (student.getId().equals(record.getStudentId())) {
                        record.setCampusName(student.getCampusName());
                        record.setStuName(student.getStuName());
                        record.setStuNumber(student.getStuNumber());
                        break;
                    }
                }
            }
        }
        return recordPage;
    }

    @Override
    @Transactional
    public void exportAttendanceResult(AttendanceResultPageDTO dto, HttpServletResponse response) {
        // 获取学生
        List<Long> studentIds = null;
        ListStudentDTO listStudentDTO = ListStudentDTO.builder().isQueryParent(false).isQuerySchoolName(false).build();
        BeanUtils.copyProperties(dto, listStudentDTO);
        // 筛选寝室
        List<Long> roomList = new ArrayList<>();
        if (dto.getDormRoomId() != null) {
            roomList.add(dto.getDormRoomId());
        } else if (dto.getDormId() != null) {
            List<EduDormitoryRoom> data = remoteDormitoryService
                .listDormRoom(ListDormRoomDTO.builder().dormIds(Collections.singletonList(dto.getDormId())).build()).getData();
            if (CollUtil.isNotEmpty(data)) {
                roomList = data.stream().map(EduDormitoryRoom::getId).collect(Collectors.toList());
            }
        }
        listStudentDTO.setDormRoomIds(roomList);
        // 查询匹配的学生
        List<EduStudent> studentList = remoteStudentService.listStudent(listStudentDTO).getData();
        if (CollUtil.isNotEmpty(studentList)) {
            if (StrUtil.isNotBlank(dto.getKeyword())) {
                studentList = studentList.stream()
                    .filter(x -> x.getStuName().contains(dto.getKeyword()) || x.getStuNumber().contains(dto.getKeyword()))
                    .collect(Collectors.toList());
            }
            if (CollUtil.isNotEmpty(studentList)) {
                studentIds = studentList.stream().map(EduStudent::getId).collect(Collectors.toList());
            }
        }
        // 考勤结果列表
        List<AttendanceResultDormVO> recordList = baseMapper.listAttendanceResult(null, studentIds, dto.getRuleId(),
            dto.getStartDate(), dto.getEndDate());
        if (CollUtil.isNotEmpty(recordList) && CollUtil.isNotEmpty(studentList)) {
            for (AttendanceResultDormVO record : recordList) {
                for (EduStudent student : studentList) {
                    if (student.getId().equals(record.getStudentId())) {
                        record.setCampusName(student.getCampusName());
                        record.setStuName(student.getStuName());
                        record.setStuNumber(student.getStuNumber());
                        break;
                    }
                }
            }
        }
        if (dto.getType() == 0) {
            ExcelUtil.export("校门考勤记录表.xlsx", AttendanceResultVO.class, recordList.stream().map(x -> {
                AttendanceResultVO vo = new AttendanceResultVO();
                BeanUtils.copyProperties(x, vo);
                return vo;
            }).collect(Collectors.toList()), response);
        } else {
            ExcelUtil.export("宿舍考勤记录表.xlsx", AttendanceResultDormVO.class, recordList, response);
        }
    }

    /**
     * 定时处理考勤记录
     */
    @Override
    public void dealAttendanceResult() {
        log.info("进入考勤统计:[{}]", LocalDateTime.now());
        List<EduAttendanceConfig> configList = eduAttendanceConfigService.list();
        if (CollUtil.isNotEmpty(configList)) {
            // 每个学校分开查询
            for (EduAttendanceConfig config : configList) {
                if (ObjectUtil.equal("1", config.getState())) {
                    LocalDateTime begin = LocalDateTime.now();
                    log.info("开始生成[{}]学校学生考勤结果", config.getSchoolId());
                    // 远程调用不放入事务  减少长事务
                    List<EduStudent> schoolStudentList =
                        remoteStudentService.listStudent(
                            ListStudentDTO.builder().isQuerySchoolName(false).isQueryParent(false).schoolId(config.getSchoolId())
                                .build()).getData();
                    generateAttendanceResultService.generateStudentAttendanceResult(config, schoolStudentList);
                    LocalDateTime end = LocalDateTime.now();
                    log.info("完成[{}]学校学生考勤结果生成,开始时间:[{}],结束时间:[{}]", config.getSchoolId(), begin, end);
                }
            }
        }
        log.info("结束考勤统计:[{}]", LocalDateTime.now());
    }


    @Override
    @Transactional
    public void pushNotArriveMsg() {
        List<EduAttendanceConfig> configList = eduAttendanceConfigService.list();
        if (CollUtil.isNotEmpty(configList)) {
            for (EduAttendanceConfig config : configList) {

                // 查询需要推送给管理员的记录 TODO 2022/7/14 此处暂时只推送一次, 也没有确认记录选项
                List<EduAttendanceResult> managePushResult = list(Wrappers.lambdaQuery(new EduAttendanceResult())
                    .eq(EduAttendanceResult::getSchoolId, config.getSchoolId())
                    .eq(EduAttendanceResult::getPushStatus, "0")
                    .in(EduAttendanceResult::getStatus,
                        CollUtil.newArrayList(AttendanceResult.STU_D_LATE, AttendanceResult.STU_D_EX_LATE)));
                if (CollUtil.isNotEmpty(managePushResult)) {
                    // 推送管理员对象
                    String[] objs = config.getDormitoryManagePushObj().split(StringConstant.COMMA);
                    for (String obj : objs) {
                        switch (obj) {
                            // 宿管
                            case "0":
                                checkDormitory(config, managePushResult);
                                break;
                            // 班主任
                            case "1":
                                checkClassHeadTeacher(config, managePushResult);
                                break;
                            // 年级长
                            case "2":
                                checkGradeHeadTeacher(config, managePushResult);
                                break;
                            // 副校长
                            case "3":
                                // TODO 2022/7/16 需要处理副校长数据
                                break;
                            default:
                                break;
                        }
                    }
                }

                // 查询需要推送给家长的记录
                LocalDateTime now = LocalDateTime.now();
                List<EduAttendanceResult> pushMessage = baseMapper
                    .listPushNotArrive(now.minusMinutes(config.getSchoolPushInterval()), config.getSchoolId());
                if (CollUtil.isNotEmpty(pushMessage)) {
                    for (EduAttendanceResult result : pushMessage) {
                        EduStudent student = (EduStudent) redisService.hget(CachePrefixConstant.STUDENT_DATA,
                            result.getStudentId().toString());
                        if (student == null) {
                            student = remoteStudentService.getStudentNoPermission(result.getStudentId()).getData();
                        }
                        if (student != null) {
                            // 推送包含家长
                            if (config.getSchoolPushObj() == 0) {
                                for (EduParent parent : student.getParents()) {
                                    //构建消息
//                                    String msg = String.format("【平安校园警告】尊敬的%s%s，截止%s，%s" +
//                                                    "并未归寝，请您尽快确认学生位置，确保学生的人身安全。<a href=\"%s\">请点击此处确认消息</a>",
//                                            student.getStuName(), parent.getParentType(),
//                                            LocalDateTimeUtil.format(now, "yyyy年MM月dd日HH时mm分秒"),
//                                            student.getStuName(), pageUrl + NOTICE_URL + "?id=" + result.getId().toString());
                                    String msg = String.format("【平安校园警告】尊敬的%s%s，截止%s，%s" +
                                            "并未归寝，请您尽快确认学生位置，确保学生的人身安全。",
                                        student.getStuName(), parent.getParentType(),
                                        LocalDateTimeUtil.format(now, "yyyy年MM月dd日HH时mm分秒"),
                                        student.getStuName());
                                    // 发送通知消息
                                    EduApp app = commonService.getAppByCodeAndSchool(AppConstant.ATTENDANCE_PARENT, null,
                                        student.getSchoolId());
                                    TextSchoolNotice notice = new TextSchoolNotice();
                                    notice.setTo_parent_userid(Collections.singletonList(parent.getWxId()));
                                    notice.setText(new Text(msg));
                                    notice.setAgentid(app.getWxAgentId());
                                    wxUtil.pushSchoolNotice(wxUtil.getAccessToken(app.getWxCorpId(), app.getWxSecret()),
                                        notice);
                                    result.setLastPushTime(now);
                                }
                            }
                            result.setNotArriveConfirm(null);
                            result.setPushStatus("1");
                        }
                    }
                    updateBatchById(pushMessage);
                }
            }
        }
    }

    /**
     * 判断宿管推送记录
     *
     * @param config           考勤配置
     * @param managePushResult 考勤记录
     * @author ZYJ
     * @date 2022/7/15 10:19
     */
    private void checkDormitory(EduAttendanceConfig config, List<EduAttendanceResult> managePushResult) {
        // 查询宿舍id
        List<Long> dormIds = managePushResult.stream().map(EduAttendanceResult::getDormId)
            .distinct().collect(Collectors.toList());

        Map<Long, List<EduAttendanceResult>> dormResults = managePushResult.stream()
            .collect(Collectors.groupingBy(EduAttendanceResult::getDormId));
        // 职工发送消息集合
        Map<Long, AttendanceResultPushVO> pushData = new ConcurrentHashMap<>(16);
        dormIds.forEach(dormId -> {

            List<Long> resultIds = dormResults.get(dormId).stream().map(EduAttendanceResult::getId).collect(Collectors.toList());
            // 根据宿舍id查询对应宿管信息
            EduDormitory dormitory = remoteDormitoryService.getDormNoPermission(dormId).getData();
            // 宿管信息
            List<EduStaff> staffList = dormitory.getEduStaffList();
            if (CollUtil.isNotEmpty(staffList)) {
                staffList.forEach(eduStaff -> {
                    // 推送信息
                    AttendanceResultPushVO attendanceResultPushVO;
                    // 记录集合
                    List<Long> list;
                    if (pushData.containsKey(eduStaff.getId())) {
                        attendanceResultPushVO = pushData.get(eduStaff.getId());
                        list = attendanceResultPushVO.getResultIds();
                        list.addAll(resultIds);
                    } else {
                        attendanceResultPushVO = new AttendanceResultPushVO();
                        attendanceResultPushVO.setEduStaff(eduStaff);
                        list = new ArrayList<>(resultIds);
                    }
                    attendanceResultPushVO.setResultIds(list);
                    pushData.put(eduStaff.getId(), attendanceResultPushVO);
                });
            }
        });
        // 推送消息
        pushData(pushData, config);
    }

    /**
     * 判断班主任推送记录
     *
     * @param config           考勤配置
     * @param managePushResult 考勤记录
     * @author ZYJ
     * @date 2022/7/15 10:19
     */
    private void checkClassHeadTeacher(EduAttendanceConfig config, List<EduAttendanceResult> managePushResult) {
        // 查询班级id
        List<Long> classIds = managePushResult.stream().map(EduAttendanceResult::getClassId)
            .distinct().collect(Collectors.toList());

        Map<Long, List<EduAttendanceResult>> classResults = managePushResult.stream()
            .collect(Collectors.groupingBy(EduAttendanceResult::getClassId));
        // 职工发送消息集合
        Map<Long, AttendanceResultPushVO> pushData = new ConcurrentHashMap<>(16);
        classIds.forEach(classId -> {
            List<Long> resultIds = classResults.get(classId).stream().map(EduAttendanceResult::getId)
                .collect(Collectors.toList());
            // 教师类型 1表示校区负责人，2表示年级负责人，3表示班主任，4表示任课老师，5表示学段负责人
            List<EduStaff> staffList = remoteTeacherService.listTeacherByDeptId(classId, "3").getData();

            staffList.forEach(staff -> {
                // 推送信息
                AttendanceResultPushVO attendanceResultPushVO;
                // 记录集合
                List<Long> list;
                if (pushData.containsKey(staff.getId())) {
                    attendanceResultPushVO = pushData.get(staff.getId());
                    list = attendanceResultPushVO.getResultIds();
                    list.addAll(resultIds);
                } else {
                    attendanceResultPushVO = new AttendanceResultPushVO();
                    attendanceResultPushVO.setEduStaff(staff);
                    list = new ArrayList<>(resultIds);
                }
                attendanceResultPushVO.setResultIds(list);
                pushData.put(staff.getId(), attendanceResultPushVO);
            });
        });
        // 推送消息
        pushData(pushData, config);
    }

    /**
     * 判断年级长推送记录
     *
     * @param config           考勤配置
     * @param managePushResult 考勤记录
     * @author ZYJ
     * @date 2022/7/16 10:20
     */
    private void checkGradeHeadTeacher(EduAttendanceConfig config, List<EduAttendanceResult> managePushResult) {
        // 查询年级id
        List<Long> gradeIds = managePushResult.stream().map(EduAttendanceResult::getGradeId)
            .distinct().collect(Collectors.toList());

        Map<Long, List<EduAttendanceResult>> gradeResults = managePushResult.stream()
            .collect(Collectors.groupingBy(EduAttendanceResult::getGradeId));
        // 职工发送消息集合
        Map<Long, AttendanceResultPushVO> pushData = new ConcurrentHashMap<>(16);
        gradeIds.forEach(gradeId -> {
            List<Long> resultIds = gradeResults.get(gradeId).stream().map(EduAttendanceResult::getId)
                .collect(Collectors.toList());
            // 教师类型 1表示校区负责人，2表示年级负责人，3表示班主任，4表示任课老师，5表示学段负责人
            List<EduStaff> staffList = remoteTeacherService.listTeacherByDeptId(gradeId, "2").getData();

            staffList.forEach(staff -> {
                // 推送信息
                AttendanceResultPushVO attendanceResultPushVO;
                // 记录集合
                List<Long> list;
                if (pushData.containsKey(staff.getId())) {
                    attendanceResultPushVO = pushData.get(staff.getId());
                    list = attendanceResultPushVO.getResultIds();
                    list.addAll(resultIds);
                } else {
                    attendanceResultPushVO = new AttendanceResultPushVO();
                    attendanceResultPushVO.setEduStaff(staff);
                    list = new ArrayList<>(resultIds);
                }
                attendanceResultPushVO.setResultIds(list);
                pushData.put(staff.getId(), attendanceResultPushVO);
            });
        });
        // 推送消息
        pushData(pushData, config);
    }

    /**
     * 推送消息
     *
     * @param pushData 职工发送消息集合
     * @param config   考勤配置
     * @author ZYJ
     * @date 2022/7/16 10:11
     */
    private void pushData(Map<Long, AttendanceResultPushVO> pushData, EduAttendanceConfig config) {
        // 判断是否需要推送消息
        if (CollUtil.isNotEmpty(pushData)) {
            EduApp app = commonService.getAppByCodeAndSchool(AppConstant.ATTENDANCE_TEACHER, null,
                config.getSchoolId());
            pushData.forEach((staffId, pushVO) -> {
                // 保存推送记录
                EduAttendanceManagePushResult attendanceManagePushResult = EduAttendanceManagePushResult.builder()
                    .createDate(LocalDateTime.now())
                    .staffId(staffId)
                    .resultId(pushVO.getResultIds().stream().map(Object::toString).collect(Collectors.joining()))
                    .build();
                eduAttendanceManagePushResultService.save(attendanceManagePushResult);

                // 推送微信消息
                NewsStaffNotice newsStaffNotice = new NewsStaffNotice();
                newsStaffNotice.setAgentid(app.getWxAgentId());
                Article article = new Article();
                // TODO 2022/7/15 此处为通知图片和点击页面地址
                article.setPicurl("");
                article.setUrl(pageUrl + MANAGE_NOTICE_URL + "?id=" + attendanceManagePushResult.getId());
                article.setTitle(LocalDateTimeUtil.format(LocalDateTime.now(), "MM月dd日") + "归寝报告");
                article.setDescription("点击查看报告详情，即时关注学生归寝情况");
                newsStaffNotice.setNews(new News(Collections.singletonList(article)));
                newsStaffNotice.setTouser(pushVO.getEduStaff().getWxId());
                wxUtil.pushStaffNotice(wxUtil.getAccessToken(app.getWxCorpId(), app.getWxSecret()), newsStaffNotice);
            });
        }
    }

    @Override
    @Transactional
    public List<RuleTimeVO> listGradeResultTime(Long gradeId, String date) {
        return baseMapper.listGradeResultTime(gradeId, date);
    }

    @Override
    @Transactional
    public List<ResultDetailVO> listStudentResultDetail(ListStudentResultDTO dto) {
        ListStudentDTOBuilder builder = ListStudentDTO.builder().isQueryParent(false).isQuerySchoolName(false)
            .isQueryUserDept(false);
        if (dto.getClassId() != null) {
            builder.classId(dto.getClassId());
        }
        if (dto.getStudentId() != null) {
            builder.studentIds(Collections.singletonList(dto.getStudentId()));
        }
        List<EduStudent> studentList = remoteStudentService.listStudent(builder.build()).getData();
        List<ResultDetailVO> details = null;
        if (CollUtil.isNotEmpty(studentList)) {
            details = baseMapper.listStudentResultDetail(dto,
                studentList.stream().map(EduStudent::getId).collect(Collectors.toList()));
            if (CollUtil.isNotEmpty(details)) {
                Map<Long, List<EduStudent>> studentGroup = studentList.stream().collect(Collectors.groupingBy(EduStudent::getId));
                for (ResultDetailVO detail : details) {
                    EduStudent student = studentGroup.get(detail.getStudentId()).get(0);
                    detail.setStudentName(student.getStuName());
                    detail.setStudentNum(student.getStuNumber());
                    detail.setStudentType(student.getType());
                }
            }
        }
        return details;
    }

    private String translateResult(Integer status) {
        AttendanceResult value = null;
        try {
            value = EnumUtils.valueOf(AttendanceResult.class, status, AttendanceResult.class.getMethod("getValue"));
        } catch (NoSuchMethodException e) {
            log.error("考勤结果值获取失败,:[{}]", status);
        }
        return value != null ? value.getName() : null;
    }
}
