package com.ym.mec.education.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ym.mec.education.base.BaseResponse;
import com.ym.mec.education.base.PageResponse;
import com.ym.mec.education.entity.*;
import com.ym.mec.education.enums.ReturnCodeEnum;
import com.ym.mec.education.enums.StudentAttendanceStatusEnum;
import com.ym.mec.education.mapper.StudentAttendanceMapper;
import com.ym.mec.education.req.AttendClassReq;
import com.ym.mec.education.req.ClassGroupReq;
import com.ym.mec.education.req.CourseScheduleReq;
import com.ym.mec.education.req.HomeWorkReq;
import com.ym.mec.education.resp.*;
import com.ym.mec.education.service.*;
import com.ym.mec.education.utils.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生考勤表 服务实现类
 * </p>
 *
 * @author lemeng
 * @since 2019-09-25
 */
@Service("IStudentAttendanceService")
public class StudentAttendanceServiceImpl extends ServiceImpl<StudentAttendanceMapper, StudentAttendance> implements IStudentAttendanceService {

    @Autowired
    private ICourseScheduleService courseScheduleService;
    @Autowired
    private IClassGroupService groupService;
    @Autowired
    private ISubjectService subjectService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private IClassGroupStudentMapperService classGroupStudentMapperService;
    @Autowired
    private IMusicGroupStudentFeeService musicGroupStudentFeeService;

    @Autowired
    private ITeacherAttendanceService teacherAttendanceService;

    @Autowired
    private ICourseHomeworkService courseHomeworkService;

    @Override
    public PageResponse getPage(ClassGroupReq classGroupReq) {
        if (Objects.isNull(classGroupReq.getGroupId())) {
            return PageResponse.errorParam();
        }
        Page<StudentAttendance> pageParam = new Page(classGroupReq.getPageNo(), classGroupReq.getPageSize());
        QueryWrapper<StudentAttendance> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Objects.nonNull(classGroupReq.getGroupId()),
                StudentAttendance::getClassGroupId, classGroupReq.getGroupId());
        IPage<StudentAttendance> page = page(pageParam, queryWrapper);
        IPage<StudentAttendanceResp> pageResult = new Page<>();
        BeanUtils.copyProperties(page, pageResult);
        List<StudentAttendanceResp> list = Lists.newArrayList();
        QueryWrapper<StudentAttendance> leaveWrapper = new QueryWrapper<>();
        QueryWrapper<StudentAttendance> normalWrapper = new QueryWrapper<>();
        //总人数
        queryWrapper.lambda().eq(StudentAttendance::getClassGroupId, classGroupReq.getGroupId());
        Integer totalCount = count(queryWrapper);
        //请假
        leaveWrapper.lambda().eq(true, StudentAttendance::getClassGroupId, classGroupReq.getGroupId())
                .eq(true, StudentAttendance::getStatus, StudentAttendanceStatusEnum.LEAVE.getCode());
        Integer leaveCount = count(leaveWrapper);
        //正常
        normalWrapper.lambda().eq(true, StudentAttendance::getClassGroupId, classGroupReq.getGroupId())
                .eq(true, StudentAttendance::getStatus, StudentAttendanceStatusEnum.NORMAL.getCode());
        Integer normalCount = count(normalWrapper);
        page.getRecords().forEach(item -> {
            StudentAttendanceResp studentAttendanceResp = new StudentAttendanceResp();
            studentAttendanceResp.setCourseScheduleId(item.getCourseScheduleId());
            studentAttendanceResp.setLeaveNum(leaveCount);
            if (totalCount != 0) {
                studentAttendanceResp.setAttendanceRate(normalCount + "/" + totalCount);
            }

            CourseSchedule courseSchedule = courseScheduleService.getById(item.getCourseScheduleId());
            if (Objects.nonNull(courseSchedule)) {
                studentAttendanceResp.setClassDate(DateUtil.date2String(courseSchedule.getClassDate())
                        + " " + DateUtil.date2Week(courseSchedule.getClassDate()))
                        .setClassTime(courseSchedule.getStartClassTime() + "-" + courseSchedule.getEndClassTime());
            }
            ClassGroup classGroup = groupService.getById(classGroupReq.getGroupId());
            if (Objects.nonNull(classGroup)) {
                studentAttendanceResp.setSubjectName(subjectService.getSubjectList(classGroup.getSubjectIdList()).stream().map(Subject::getName).collect(Collectors.toList()));
                list.add(studentAttendanceResp);
            }
        });
        pageResult.setRecords(list);
        return PageResponse.success(pageResult);
    }

    @Override
    public PageResponse getPageByCourse(CourseScheduleReq courseScheduleReq) {
        if (Objects.isNull(courseScheduleReq.getCourseScheduleId())) {
            return PageResponse.errorParam();
        }
        CourseSchedule courseSchedule = courseScheduleService.getById(courseScheduleReq.getCourseScheduleId());
        Page<StudentAttendanceResp> pageResult = new Page<>();
        if (Objects.nonNull(courseSchedule)) {
            Page<StudentAttendance> studentAttendancePage = new Page<StudentAttendance>(courseScheduleReq.getPageNo(), courseScheduleReq.getPageSize());
            QueryWrapper<StudentAttendance> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(true, StudentAttendance::getCourseScheduleId, courseScheduleReq.getCourseScheduleId())
                    .eq(true, StudentAttendance::getCourseScheduleId, courseSchedule.getId());
            IPage<StudentAttendance> page = page(studentAttendancePage, queryWrapper);
            if (!CollectionUtils.isEmpty(page.getRecords())) {
                List<StudentAttendanceResp> list = Lists.newArrayList();
                page.getRecords().forEach(item -> {
                    StudentAttendanceResp studentAttendanceResp = new StudentAttendanceResp();
                    if (Objects.nonNull(item.getUserId())) {
                        SysUser user = userService.getById(item.getUserId());
                        if (Objects.nonNull(user) && StringUtils.isNotBlank(user.getRealName())) {
                            studentAttendanceResp.setStudentName(user.getRealName());
                        }
                    }
                    if (StringUtils.isNotBlank(item.getStatus())) {
                        studentAttendanceResp.setStatus(StudentAttendanceStatusEnum.getMsgByCode(item.getStatus()));
                    }
                    list.add(studentAttendanceResp);
                });
                pageResult.setRecords(list);
            }
        }
        return PageResponse.success(pageResult);
    }

    @Override
    public PageResponse statisticsList(ClassGroupReq classGroupReq) {
        if (Objects.isNull(classGroupReq.getGroupId())) {
            PageResponse.errorParam();
        }
        Page<StudentAttendanceStatisticsResp> pageResult = new Page();
        ClassGroup classGroup = groupService.getById(classGroupReq.getGroupId());
        if (Objects.nonNull(classGroup)) {
            List<String> subjectNameList;
            if (Objects.nonNull(classGroupReq.getSubjectId())) {
                subjectNameList = Lists.newArrayList(subjectService.getById(classGroupReq.getSubjectId()).getName());
            } else {
                subjectNameList = subjectService.getSubjectList(classGroup.getSubjectIdList()).stream().map(Subject::getName).collect(Collectors.toList());
            }
            Page<ClassGroupStudentMapper> studentMapperPage = classGroupStudentMapperService.selectPageByCondition(classGroupReq);
            if (!CollectionUtils.isEmpty(studentMapperPage.getRecords())) {
                List<StudentAttendanceStatisticsResp> studentAttendanceStatisticsRespList = Lists.newArrayList();
                BeanUtils.copyProperties(studentMapperPage, pageResult);
                List<String> finalSubjectNameList = subjectNameList;
                studentMapperPage.getRecords().forEach(item -> {
                    StudentAttendanceStatisticsResp resp = new StudentAttendanceStatisticsResp();
                    SysUser user = userService.getById(item.getUserId());
                    if (Objects.nonNull(user) && StringUtils.isNotBlank(user.getRealName())) {
                        resp.setStudentName(user.getRealName());
                    }
                    resp.setSubjectName(finalSubjectNameList);
                    //是否连续旷课
                    QueryWrapper<MusicGroupStudentFee> musicGroupStudentFeeQueryWrapper = new QueryWrapper<MusicGroupStudentFee>();
                    musicGroupStudentFeeQueryWrapper.lambda().eq(true, MusicGroupStudentFee::getMusicGroupId, classGroup.getMusicGroupId())
                            .eq(true, MusicGroupStudentFee::getUserId, item.getUserId());
                    MusicGroupStudentFee musicGroupStudentFee = musicGroupStudentFeeService.getOne(musicGroupStudentFeeQueryWrapper);
                    if (Objects.nonNull(musicGroupStudentFee) && Objects.nonNull(musicGroupStudentFee.getContinuousAbsenteeismTimes())) {
                        if (musicGroupStudentFee.getContinuousAbsenteeismTimes() > 1) {
                            resp.setTruant(true);
                        }
                    }
                    //到课天数
                    QueryWrapper<StudentAttendance> normalWrapper = new QueryWrapper<>();
                    normalWrapper.lambda().eq(true, StudentAttendance::getClassGroupId, classGroupReq.getGroupId())
                            .eq(true, StudentAttendance::getUserId, item.getUserId())
                            .eq(true, StudentAttendance::getStatus, StudentAttendanceStatusEnum.NORMAL.getCode());
                    int normalDay = count(normalWrapper);
                    //旷课天数
                    QueryWrapper<StudentAttendance> truantWrapper = new QueryWrapper<>();
                    truantWrapper.lambda().eq(true, StudentAttendance::getCourseScheduleId, classGroupReq.getGroupId())
                            .eq(true, StudentAttendance::getUserId, item.getUserId())
                            .eq(true, StudentAttendance::getStatus, StudentAttendanceStatusEnum.TRUANT.getCode());
                    int truantDay = count(truantWrapper);
                    //请假天数
                    QueryWrapper<StudentAttendance> leaveWrapper = new QueryWrapper<>();
                    leaveWrapper.lambda().eq(true, StudentAttendance::getCourseScheduleId, classGroupReq.getGroupId())
                            .eq(true, StudentAttendance::getUserId, item.getUserId())
                            .eq(true, StudentAttendance::getStatus, StudentAttendanceStatusEnum.LEAVE.getCode());
                    int leaveDay = count(leaveWrapper);
                    resp.setNormalDay(normalDay);
                    resp.setTruantDay(truantDay);
                    resp.setLeaveDay(leaveDay);
                    //每个学生的考勤明细
                    QueryWrapper<StudentAttendance> studentAttendanceQueryWrapper = new QueryWrapper<>();
                    studentAttendanceQueryWrapper.lambda().eq(true, StudentAttendance::getClassGroupId, classGroupReq.getGroupId())
                            .eq(true, StudentAttendance::getUserId, item.getUserId());
                    List<StudentAttendance> studentAttendanceList = list(studentAttendanceQueryWrapper);
                    List<StudentAttendanceResp> studentAttendanceRespList = Lists.newArrayList();
                    if (!CollectionUtils.isEmpty(studentAttendanceList)) {
                        studentAttendanceList.forEach(studentAttendance -> {
                            StudentAttendanceResp studentAttendanceResp = new StudentAttendanceResp();
                            if (Objects.nonNull(studentAttendance.getCreateTime())) {
                                studentAttendanceResp.setClassDate(DateUtil.date2String(studentAttendance.getCreateTime(),
                                        DateUtil.DATE_FORMAT)).setClassWeek(DateUtil.date2Week(studentAttendance.getCreateTime()));
                            }
                            if (StringUtils.isNotBlank(studentAttendance.getStatus())) {
                                studentAttendanceResp.setStatus(StudentAttendanceStatusEnum.getMsgByCode(studentAttendance.getStatus()));
                            }
                            studentAttendanceRespList.add(studentAttendanceResp);
                        });
                    }
                    resp.setList(studentAttendanceRespList);
                    studentAttendanceStatisticsRespList.add(resp);
                });
                pageResult.setRecords(studentAttendanceStatisticsRespList);
            }
        }
        return PageResponse.success(pageResult);
    }

    @Override
    public PageResponse attendRecordList(AttendClassReq req) {

        PageResponse<AttendClassResp> response = new PageResponse();
        Page<StudentAttendance> pageParam = new Page(req.getPageNo(), req.getPageSize());

        Page<AttendClassResp>  attendClassRespPage = this.baseMapper.selectPageByCondition(pageParam,req);

        List<AttendClassResp> respList = attendClassRespPage.getRecords();
        if(!CollectionUtils.isEmpty(respList)){

            respList.forEach(e->{

                e.setDateStr(DateUtil.date2String(e.getClassDate(),DateUtil.DATE_FORMAT));
                e.setStartTime(DateUtil.date2String(e.getStartClassTime(),DateUtil.TIME_FORMAT));
                e.setEndTime(DateUtil.date2String(e.getEndClassTime(),DateUtil.TIME_FORMAT));
                e.setWeek(DateUtil.date2Week(e.getClassDate()));
            });


        }
        return PageResponse.success(pageParam);
    }

    @Override
    public PageResponse callStudent(HomeWorkReq req) {
        if(req == null || req.getCourseScheduleId() == null){
            return  PageResponse.errorParam();
        }
        PageResponse response = new PageResponse();

        IPage<StudentAttendance> page = new Page<StudentAttendance>(req.getPageNo(),req.getPageSize());
        QueryWrapper<StudentAttendance> queryWrapper = new QueryWrapper<StudentAttendance>();
        queryWrapper.eq("course_schedule_id_",req.getCourseScheduleId());
        if(req.getStatus() != null){
            queryWrapper.eq("status_",req.getStatus());
        }
        IPage<StudentAttendance> studentAttendanceIPage = this.page(page,queryWrapper);

        List<CallStudentResp> callStudentResps = new ArrayList<>();
        List<StudentAttendance> studentAttendanceList = studentAttendanceIPage.getRecords();
        if(!CollectionUtils.isEmpty(studentAttendanceList)){

            studentAttendanceList.forEach(e->{
                CallStudentResp callStudentResp = new CallStudentResp();
                callStudentResp.setUserId(e.getUserId());
                SysUser sysUser = userService.getById(e.getUserId());
                if(sysUser != null ){
                    callStudentResp.setName(sysUser.getRealName());
                    callStudentResp.setAvatar(sysUser.getAvatar());
                }
                callStudentResp.setStatus(e.getStatus());
                callStudentResps.add(callStudentResp);
            });


        }

        response.setTotal(Math.toIntExact(page.getTotal()));
        response.setSize(Math.toIntExact(page.getSize()));
        response.setCurrent(Math.toIntExact(page.getCurrent()));
        response.setRecords(callStudentResps);
        response.setReturnCode(ReturnCodeEnum.CODE_200.getCode());
        return response;
    }

    @Override
    public BaseResponse signInfo(HomeWorkReq req) {

        if(req == null || req.getCourseScheduleId() == null){
            return  BaseResponse.errorParam();
        }

        SignInfoResp signInfoResp = new SignInfoResp();
        QueryWrapper<TeacherAttendance> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("course_schedule_id_",req.getCourseScheduleId());
        TeacherAttendance teacherAttendance = teacherAttendanceService.getOne(queryWrapper);
        if(teacherAttendance != null){
            signInfoResp.setSignInTime(DateUtil.date2String(teacherAttendance.getSignInTime(),DateUtil.DATE_FORMAT_DATE));
            signInfoResp.setSignOutTime(DateUtil.date2String(teacherAttendance.getSignOutTime(),DateUtil.DATE_FORMAT_DATE));
        }
        QueryWrapper<CourseHomework> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("course_schedule_id_",req.getCourseScheduleId());
        CourseHomework courseHomework = courseHomeworkService.getOne(queryWrapper1);
        if(courseHomework != null){
            signInfoResp.setContent(courseHomework.getContent());
            if(courseHomework.getAttachments()!= null){
                String[] str = courseHomework.getAttachments().split(",");
                signInfoResp.setAttachments(Arrays.asList(str));
            }

        }

        return BaseResponse.success(signInfoResp);
    }

}
