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.CourseStatusEnum;
import com.ym.mec.education.enums.StudentAttendanceStatusEnum;
import com.ym.mec.education.enums.TeachModeEnum;
import com.ym.mec.education.enums.TeachTypeEnum;
import com.ym.mec.education.mapper.CourseScheduleMapper;
import com.ym.mec.education.req.ClassGroupReq;
import com.ym.mec.education.req.CourseScheduleReq;
import com.ym.mec.education.req.StudentReq;
import com.ym.mec.education.resp.CourseInfoResp;
import com.ym.mec.education.resp.CourseScheduleResp;
import com.ym.mec.education.resp.StudentResp;
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.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程计划表 服务实现类
 * </p>
 *
 * @author lemeng
 * @since 2019-09-25
 */
@Service("ICourseScheduleService")
public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleMapper, CourseSchedule> implements ICourseScheduleService {

    @Autowired
    private IClassGroupService groupService;
    @Autowired
    private IClassGroupTeacherMapperService classGroupTeacherMapperService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISubjectService subjectService;
    @Autowired
    private IStudentAttendanceService studentAttendanceService;
    @Autowired
    private IMusicGroupQuitService musicGroupQuitService;
    @Autowired
    private IClassGroupStudentMapperService classGroupStudentMapperService;
    @Autowired
    private IClassGroupService classGroupService;
    @Autowired
    private IMusicGroupService musicGroupService;
    @Autowired
    private ISchoolService schoolService;
    @Autowired
    private IMusicGroupStudentFeeService studentFeeService;
    @Autowired
    private IVipGroupClassGroupMapperService vipGroupClassGroupMapperService;
    @Autowired
    private IVipGroupService vipGroupService;

    @Override
    public PageResponse getPage(ClassGroupReq classGroupReq) {
        if (Objects.isNull(classGroupReq.getGroupId())) {
            return PageResponse.errorParam();
        }
        Page<CourseSchedule> courseSchedulePage = new Page<CourseSchedule>(classGroupReq.getPageNo(), classGroupReq.getPageSize());
        QueryWrapper<CourseSchedule> courseScheduleQueryWrapper = new QueryWrapper<>();
        courseScheduleQueryWrapper.lambda().eq(true, CourseSchedule::getClassGroupId, classGroupReq.getGroupId());
        IPage<CourseSchedule> courseScheduleIPage = page(courseSchedulePage, courseScheduleQueryWrapper);
        Page<CourseScheduleResp> pageResult = new Page<>();
        List<CourseScheduleResp> courseScheduleRespList = Lists.newArrayList();
        BeanUtils.copyProperties(courseScheduleIPage, pageResult);
        ClassGroup classGroup = groupService.getById(classGroupReq.getGroupId());
        courseScheduleIPage.getRecords().forEach(item -> {
            CourseScheduleResp courseScheduleResp = new CourseScheduleResp();
            courseScheduleResp.setId(item.getId());
            if (Objects.nonNull(item.getClassDate())) {
                courseScheduleResp.setClassDate(DateUtil.date2String(item.getClassDate())
                    + " " + DateUtil.date2Week(item.getClassDate()));
            }
            if (Objects.nonNull(item.getStartClassTime()) && Objects.nonNull(item.getEndClassTime())) {
                courseScheduleResp.setClassTime(DateUtil.time2String(item.getStartClassTime()) + "-" +
                    DateUtil.time2String(item.getEndClassTime()));
            }
            if (StringUtils.isNotBlank(classGroup.getSubjectIdList())) {
                List<String> subjectNameList = subjectService.getSubjectList(classGroup.getSubjectIdList()).stream().map(Subject::getName).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(subjectNameList)) {
                    courseScheduleResp.setSubjectName(subjectNameList);
                }
            }
            QueryWrapper<ClassGroupTeacherMapper> classGroupTeacherMapperQueryWrapper = new QueryWrapper<>();
            classGroupTeacherMapperQueryWrapper.lambda().eq(ClassGroupTeacherMapper::getClassGroupId, item.getClassGroupId())
                .eq(ClassGroupTeacherMapper::getTeacherRole, TeachTypeEnum.BISHOP.getCode())
                .eq(ClassGroupTeacherMapper::getUserId, item.getTeacherId());
            ClassGroupTeacherMapper classGroupTeacherMapper = classGroupTeacherMapperService.getOne(classGroupTeacherMapperQueryWrapper);
            if (Objects.nonNull(classGroupTeacherMapper)) {
                SysUser sysUser = sysUserService.getById(classGroupTeacherMapper.getUserId());
                if (Objects.nonNull(sysUser)) {
                    courseScheduleResp.setTeacher(sysUser.getRealName());
                }
            }
            courseScheduleRespList.add(courseScheduleResp);
        });
        pageResult.setRecords(courseScheduleRespList);
        return PageResponse.success(pageResult);
    }

    @Override
    public BaseResponse<CourseScheduleResp> getInfo(CourseScheduleReq courseScheduleReq) {
        if (Objects.isNull(courseScheduleReq.getCourseScheduleId())) {
            return BaseResponse.errorParam();
        }
        CourseScheduleResp courseScheduleResp = new CourseScheduleResp();
        CourseSchedule courseSchedule = getById(courseScheduleReq.getCourseScheduleId());
        if (Objects.nonNull(courseSchedule)) {
            if (Objects.nonNull(courseSchedule.getClassDate())) {
                courseScheduleResp.setClassDate(DateUtil.date2String(courseSchedule.getClassDate()) + "(" +
                    DateUtil.date2Week(courseSchedule.getClassDate()) + ")");
            }
            if (Objects.nonNull(courseSchedule.getStartClassTime()) &&
                Objects.nonNull(courseSchedule.getEndClassTime())) {
                courseScheduleResp.setClassTime(DateUtil.time2String(courseSchedule.getStartClassTime()) + "-" +
                    DateUtil.time2String(courseSchedule.getEndClassTime()));
            }
            if (Objects.nonNull(courseSchedule.getTeacherId())) {
                Optional.of(sysUserService.getById(courseSchedule.getTeacherId())).
                    ifPresent(sysUser -> courseScheduleResp.setTeacher(sysUser.getRealName()));
            }
            QueryWrapper<StudentAttendance> studentAttendanceQueryWrapper = new QueryWrapper<>();
            studentAttendanceQueryWrapper.lambda().eq(true, StudentAttendance::getCourseScheduleId, courseSchedule.getId())
                .orderByDesc(true, StudentAttendance::getCreateTime);
            List<StudentAttendance> studentAttendanceList = studentAttendanceService.list(studentAttendanceQueryWrapper);
            if (!CollectionUtils.isEmpty(studentAttendanceList)) {
                studentAttendanceList.stream().findFirst().ifPresent(studentAttendance ->
                    courseScheduleResp.setLastCommitDate(DateUtil.date2String(studentAttendance.getCreateTime(), DateUtil.DATE_FORMAT_HOUR)));
            }
            QueryWrapper<StudentAttendance> leaveWrapper = new QueryWrapper<>();
            QueryWrapper<StudentAttendance> normalWrapper = new QueryWrapper<>();
            //总人数
            Integer totalCount = count();
            //请假
            leaveWrapper.lambda().eq(true, StudentAttendance::getCourseScheduleId, courseSchedule.getId())
                .eq(true, StudentAttendance::getStatus, StudentAttendanceStatusEnum.LEAVE.getCode());
            Integer leaveCount = studentAttendanceService.count(leaveWrapper);
            //正常
            normalWrapper.lambda().eq(true, StudentAttendance::getCourseScheduleId, courseSchedule.getId())
                .eq(true, StudentAttendance::getStatus, StudentAttendanceStatusEnum.NORMAL.getCode());
            Integer normalCount = studentAttendanceService.count(normalWrapper);
            courseScheduleResp.setLeaveNum(leaveCount);
            if (totalCount != 0) {
                courseScheduleResp.setAttendanceRate(normalCount + "/" + totalCount);
            }
            //当前时间
            courseScheduleResp.setClassDate(DateUtil.date2String(new Date()) + " " + DateUtil.date2Week(new Date()));
        }
        return BaseResponse.success(courseScheduleResp);
    }

    @Override
    public BaseResponse getStatisticsInfo(ClassGroupReq classGroupReq) {
        if (Objects.isNull(classGroupReq.getGroupId())) {
            return BaseResponse.errorParam();
        }
        ClassGroup classGroup = groupService.getById(classGroupReq.getGroupId());
        CourseScheduleResp courseScheduleResp = new CourseScheduleResp();
        if (Objects.nonNull(classGroup)) {
            if (Objects.nonNull(classGroup.getCurrentClassTimes()) && Objects.nonNull(classGroup.getTotalClassTimes())) {
                courseScheduleResp.setAlreadyInClass(classGroup.getCurrentClassTimes() + "/" + classGroup.getTotalClassTimes());
            }
            if (Objects.nonNull(classGroup.getStudentNum())) {
                courseScheduleResp.setStudentNum(classGroup.getStudentNum());
            }
            //退团人数
            QueryWrapper<MusicGroupQuit> musicGroupQuitQueryWrapper = new QueryWrapper<>();
            musicGroupQuitQueryWrapper.lambda().eq(true, MusicGroupQuit::getMusicGroupId, classGroup.getMusicGroupId());
            int leagueNum = musicGroupQuitService.count(musicGroupQuitQueryWrapper);
            courseScheduleResp.setLeagueNum(leagueNum);
        }
        return BaseResponse.success(courseScheduleResp);
    }

    @Override
    public BaseResponse getCourseScheduleByStudent(StudentReq studentReq) {
        if (Objects.isNull(studentReq.getStudentId())) {
            return BaseResponse.errorParam();
        }
        StudentResp studentResp = new StudentResp();
        QueryWrapper<ClassGroupStudentMapper> classGroupStudentMapperQueryWrapper = new QueryWrapper<>();
        classGroupStudentMapperQueryWrapper.lambda().eq(ClassGroupStudentMapper::getUserId, studentReq.getStudentId());
        List<ClassGroupStudentMapper> classGroupStudentMapperList = classGroupStudentMapperService.list(classGroupStudentMapperQueryWrapper);
        if (!CollectionUtils.isEmpty(classGroupStudentMapperList)) {
            classGroupStudentMapperList.forEach(classGroupStudentMapper -> {
                ClassGroup classGroup = classGroupService.getById(classGroupStudentMapper.getClassGroupId());
                if (Objects.nonNull(classGroup)) {
                    QueryWrapper<CourseSchedule> courseScheduleQueryWrapper = new QueryWrapper<>();
                    courseScheduleQueryWrapper.lambda().eq(CourseSchedule::getClassGroupId, classGroup.getId())
                        .in(CourseSchedule::getStatus, CourseStatusEnum.UNDERWAY.getCode(), CourseStatusEnum.OVER.getCode());
                    List<CourseSchedule> courseScheduleList = list(courseScheduleQueryWrapper);
                    //进行中的课程计划
                    if (!CollectionUtils.isEmpty(courseScheduleList)) {
                        List<StudentResp.StudentCourseSchedule> inProgressCourseSchedule = getCourseSchduleList(courseScheduleList.stream().filter(courseSchedule ->
                            courseSchedule.getStatus().equals(CourseStatusEnum.UNDERWAY.getCode())).collect(Collectors.toList()), classGroup, studentReq);
                        studentResp.setInProgressCourseSchedule(inProgressCourseSchedule);
                        //已完成的课程计划
                        List<StudentResp.StudentCourseSchedule> completedCourseSchedule = getCourseSchduleList(courseScheduleList.stream().filter(courseSchedule ->
                            courseSchedule.getStatus().equals(CourseStatusEnum.OVER.getCode())).collect(Collectors.toList()), classGroup, studentReq);
                        studentResp.setCompletedCourseSchedule(completedCourseSchedule);
                    }
                }
            });
        }
        return BaseResponse.success(studentResp);
    }

    /**
     * 获取课程计划
     *
     * @param courseScheduleList
     * @param classGroup
     * @return
     */
    private List<StudentResp.StudentCourseSchedule> getCourseSchduleList(List<CourseSchedule> courseScheduleList, ClassGroup classGroup, StudentReq studentReq) {
        if (!CollectionUtils.isEmpty(courseScheduleList)) {
            List<StudentResp.StudentCourseSchedule> studentCourseScheduleList = Lists.newArrayList();
            courseScheduleList.forEach(courseSchedule -> {
                StudentResp.StudentCourseSchedule studentCourseSchedule = StudentResp.getStudentCourseSchedule();
                QueryWrapper<MusicGroupStudentFee> studentFeeQueryWrapper = new QueryWrapper<>();
                studentFeeQueryWrapper.lambda().eq(MusicGroupStudentFee::getMusicGroupId, classGroup.getMusicGroupId())
                    .eq(MusicGroupStudentFee::getUserId, studentReq.getStudentId());
                MusicGroupStudentFee musicGroupStudentFee = studentFeeService.getOne(studentFeeQueryWrapper);
                Optional.ofNullable(courseSchedule.getClassDate()).ifPresent(classDate ->
                    studentCourseSchedule.setClassDate(DateUtil.date2String(courseSchedule.getClassDate()))
                        .setClassWeek(DateUtil.date2Week2(courseSchedule.getClassDate())));
                if (Objects.nonNull(courseSchedule.getStartClassTime()) && Objects.nonNull(courseSchedule.getEndClassTime())) {
                    studentCourseSchedule.setClassTime(DateUtil.time2String(courseSchedule.getStartClassTime()) + "-"
                        + DateUtil.time2String(courseSchedule.getEndClassTime()))
                        .setTotalClassTimes(DateUtil.timeDifference(courseSchedule.getStartClassTime(), courseSchedule.getEndClassTime()) + "分钟/次,共" +
                            classGroup.getTotalClassTimes() + "节");
                }

                //乐团课(单技课，合奏课，综合课，小班)
                if (CourseSchedule.CourseScheduleType.SINGLE.getCode().equals(courseSchedule.getType()) ||
                    CourseSchedule.CourseScheduleType.MIX.getCode().equals(courseSchedule.getType()) ||
                    CourseSchedule.CourseScheduleType.COMPREHENSIVE.getCode().equals(courseSchedule.getType()) ||
                    CourseSchedule.CourseScheduleType.HIGH.getCode().equals(courseSchedule.getType())) {
                    MusicGroup musicGroup = musicGroupService.getById(classGroup.getMusicGroupId());
                    Optional.ofNullable(musicGroup).ifPresent(musicGroupParam -> {
                        studentCourseSchedule.setMusicGroupName(musicGroupParam.getName());
                        studentCourseSchedule.setMusicGroupId(classGroup.getMusicGroupId());
                        School school = schoolService.getById(musicGroup.getSchoolId());
                        Optional.ofNullable(school).ifPresent(value -> studentCourseSchedule.
                            setSchoolName(value.getName()));
                    });
                    QueryWrapper<MusicGroupPaymentCalender> paymentCalenderQueryWrapper = new QueryWrapper<>();
                    paymentCalenderQueryWrapper.lambda().eq(MusicGroupPaymentCalender::getMusicGroupId, musicGroup.getId());
                    studentCourseSchedule.setCourseType(1);
                    //续费状态
                    if (Objects.nonNull(musicGroupStudentFee)) {
                        studentCourseSchedule.setRenewStatus("已缴费");
                    }
                } else if (CourseSchedule.CourseScheduleType.VIP.getCode().equals(courseSchedule.getType())) {
                    //VIP
                    studentCourseSchedule.setCourseName(courseSchedule.getName()).setClassName(classGroup.getName());
                    if (Objects.nonNull(classGroup.getTotalClassTimes()) && Objects.nonNull(classGroup.getCurrentClassTimes())) {
                        studentCourseSchedule.setRemainderClassTimes(classGroup.getTotalClassTimes() - classGroup.getCurrentClassTimes());
                    }
                    QueryWrapper<VipGroupClassGroupMapper> vipGroupClassGroupMapperQueryWrapper = new QueryWrapper<>();
                    vipGroupClassGroupMapperQueryWrapper.lambda().eq(VipGroupClassGroupMapper::getClassGroupId, courseSchedule.getClassGroupId());
                    VipGroupClassGroupMapper vipGroupClassGroupMapper = vipGroupClassGroupMapperService.getOne(vipGroupClassGroupMapperQueryWrapper);
                    if (Objects.nonNull(vipGroupClassGroupMapper)) {
                        VipGroup vipGroup = vipGroupService.getById(vipGroupClassGroupMapper.getVipGroupId());
                        Optional.ofNullable(vipGroup).ifPresent(vipGroupParam -> {
                            studentCourseSchedule.setMusicGroupId(classGroup.getMusicGroupId());
                            School school = schoolService.getById(vipGroupParam.getTeacherSchoolId());
                            Optional.ofNullable(school).ifPresent(value -> studentCourseSchedule.
                                setSchoolName(value.getName()));
                        });
                    }
                    studentCourseSchedule.setCourseType(2);
                    if (Objects.isNull(musicGroupStudentFee.getNextPaymentDate())) {
                        studentCourseSchedule.setRenewStatus("未续费");
                    } else {
                        studentCourseSchedule.setRenewStatus("已续费");
                    }
                    SysUser teacher = sysUserService.getById(courseSchedule.getTeacherId());
                    if (Objects.nonNull(teacher)) {
                        //讲课老师
                        studentCourseSchedule.setTeacher(teacher.getRealName());
                    }
                    //教学形式
                    studentCourseSchedule.setTeachMode(TeachModeEnum.getMsgByCode(courseSchedule.getTeachMode()));
                    //上课学生
                    QueryWrapper<ClassGroupStudentMapper> classGroupStudentMapperQueryWrapper = new QueryWrapper<>();
                    classGroupStudentMapperQueryWrapper.lambda().eq(ClassGroupStudentMapper::getClassGroupId, courseSchedule.getClassGroupId());
                    List<ClassGroupStudentMapper> groupStudentMapperList = classGroupStudentMapperService.list(classGroupStudentMapperQueryWrapper);
                    if (!CollectionUtils.isEmpty(groupStudentMapperList)) {
                        QueryWrapper<SysUser> sysUserQueryWrapper = new QueryWrapper<>();
                        sysUserQueryWrapper.lambda().in(SysUser::getId, groupStudentMapperList.stream().map(ClassGroupStudentMapper::getUserId).collect(Collectors.toList()));
                        List<SysUser> sysUserList = sysUserService.list(sysUserQueryWrapper);
                        if (!CollectionUtils.isEmpty(sysUserList)) {
                            studentCourseSchedule.setStudentList(sysUserList.stream().map(SysUser::getRealName).collect(Collectors.toList()));
                        }
                    }
                }
                studentCourseScheduleList.add(studentCourseSchedule);
            });
            return studentCourseScheduleList;
        }
        return Collections.emptyList();
    }

    @Override
    public BaseResponse courseInfo(CourseScheduleReq courseScheduleReq) {


        if (courseScheduleReq.getCourseScheduleId() == null) {
            return BaseResponse.failParams();
        }
        CourseInfoResp resp = new CourseInfoResp();
        CourseSchedule courseSchedule = this.baseMapper.selectById(courseScheduleReq.getCourseScheduleId());
        if (courseSchedule != null) {
            resp.setCourseName(courseSchedule.getName());
            resp.setClassDate(DateUtil.date2String(courseSchedule.getClassDate(), DateUtil.DATE_FORMAT));
            resp.setCourseScheduleId(courseSchedule.getId());
            resp.setStartClassTime(DateUtil.date2String(courseSchedule.getStartClassTime(), DateUtil.TIME_FORMAT));
            resp.setEndClassTime(DateUtil.date2String(courseSchedule.getEndClassTime(), DateUtil.TIME_FORMAT));
            resp.setWeek(DateUtil.date2Week(courseSchedule.getClassDate()));

            SysUser sysUser = sysUserService.getById(courseSchedule.getTeacherId());
            if (sysUser != null) {
                resp.setRealName(sysUser.getRealName());
            }
            ClassGroup classGroup = groupService.getById(courseSchedule.getClassGroupId());
            if (classGroup != null) {
                MusicGroup musicGroup = musicGroupService.getById(courseSchedule.getClassGroupId());
                if (musicGroup != null && musicGroup.getSchoolId() != null) {
                    School school = schoolService.getById(musicGroup.getSchoolId());
                    if (school != null) {
                        resp.setSchoolName(school.getName());
                    }
                }
            }
            QueryWrapper<StudentAttendance> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("course_schedule_id_",courseSchedule.getId());
            List<StudentAttendance> attendanceList =  studentAttendanceService.list(queryWrapper);
            if(!CollectionUtils.isEmpty(attendanceList)){
                resp.setTotalNum(attendanceList.size());

               List<StudentAttendance>  leaveList = attendanceList.stream().filter(e->StudentAttendanceStatusEnum.LEAVE.getCode().equals(e.getStatus())).collect(Collectors.toList());
               if(!CollectionUtils.isEmpty(leaveList)){
                   resp.setLeaveNum(leaveList.size());
                   resp.setActualNum(attendanceList.size() - leaveList.size());
               }
            }

        }
        return BaseResponse.success(resp);
    }
}
