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.*;
import com.ym.mec.education.mapper.TeacherMapper;
import com.ym.mec.education.req.TeacherReq;
import com.ym.mec.education.resp.TeacherDailyScheduleResp;
import com.ym.mec.education.resp.TeacherDetailResp;
import com.ym.mec.education.resp.TeacherResp;
import com.ym.mec.education.resp.VipGroupClassResp;
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.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * <p>
 * 教师表 服务实现类
 * </p>
 *
 * @author lemeng
 * @since 2019-09-25
 */
@Service("ITeacherService")
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements ITeacherService {

    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISubjectService subjectService;
    @Autowired
    private IClassGroupService classGroupService;
    @Autowired
    private IDemoGroupService demoGroupService;
    @Autowired
    private IClassGroupTeacherMapperService classGroupTeacherMapperService;
    @Autowired
    private IDemoGroupCoursesPlanService iDemoGroupCoursesPlanService;
    @Autowired
    private ITeacherLeaveRecordService teacherLeaveRecordService;
    @Autowired
    private IVipGroupService vipGroupService;
    @Autowired
    private IVipGroupCategoryService vipGroupCategoryService;
    @Autowired
    private ICourseScheduleService courseScheduleService;
    @Autowired
    private ITeacherAttendanceService teacherAttendanceService;
    @Autowired
    private IStudentAttendanceService studentAttendanceService;
    @Autowired
    private IMusicGroupService musicGroupService;
    @Autowired
    private ISchoolService schoolService;

    @Override
    public PageResponse teacherList(TeacherReq req) {
        PageResponse response = new PageResponse();
        QueryWrapper<SysUser> userQueryWrapper = new QueryWrapper<>();
        if (Objects.isNull(req)||Objects.isNull(req.getUserId())) {
            return PageResponse.errorParam();
        }
        Teacher teacher = getById(req.getUserId());
        if (Objects.isNull(teacher)) {
            return PageResponse.noDataExists();
        }
        if (req != null && StringUtils.isNotBlank(req.getName())) {
            userQueryWrapper.like("real_name_", req.getName());
        }
        List<SysUser> userList = sysUserService.list(userQueryWrapper);
        QueryWrapper<Teacher> queryWrapper = new QueryWrapper<>();
        List<TeacherResp> teacherRespList = new ArrayList<>();
        List<Integer> userIds;
        IPage<Teacher> teacherIPage = new Page<>();
        if (!CollectionUtils.isEmpty(userList)) {
            userIds = userList.stream().map(SysUser::getId).collect(Collectors.toList());
            queryWrapper.in("id_", userIds);
            Optional.ofNullable(teacher.getOrganId()).ifPresent(organId ->
                queryWrapper.lambda().eq(Teacher::getOrganId, organId));
            IPage<Teacher> page = new Page(req.getPageNo() == null ? 1 : req.getPageNo(), req.getPageSize() == null ? 10 : req.getPageSize());
            teacherIPage = this.page(page, queryWrapper);
            List<Teacher> teacherList = teacherIPage.getRecords();
            if (!CollectionUtils.isEmpty(teacherList)) {
                teacherList.forEach(e -> {
                    TeacherResp teacherResp = new TeacherResp();
                    String ids[] = e.getSubjectId().split(",");
                    List<String> stringB = Arrays.asList(ids);
                    QueryWrapper<Subject> queryWrapperSub = new QueryWrapper<>();
                    queryWrapperSub.in("id_", stringB);
                    List<Subject> subjectList = subjectService.list(queryWrapperSub);
                    if (!CollectionUtils.isEmpty(subjectList)) {
                        List<String> subName = subjectList.stream().map(Subject::getName).collect(Collectors.toList());
                        teacherResp.setSubjectName(subName);
                    }
                    teacherResp.setUserId(e.getId());
                    SysUser sysUser = sysUserService.getById(e.getId());
                    if (sysUser != null) {
                        teacherResp.setAvatar(sysUser.getAvatar());
                        teacherResp.setName(sysUser.getRealName());
                    }
                    QueryWrapper<ClassGroupTeacherMapper> queryWrapper1 = new QueryWrapper<>();
                    queryWrapper1.eq("user_id_", e.getId());
                    List<ClassGroupTeacherMapper> classGroupTeacherMappers = classGroupTeacherMapperService.list(queryWrapper1);
                    if (!CollectionUtils.isEmpty(classGroupTeacherMappers)) {
                        List<Integer> classId = classGroupTeacherMappers.stream().map(ClassGroupTeacherMapper::getClassGroupId).collect(Collectors.toList());
                        QueryWrapper<ClassGroup> groupQueryWrapper = new QueryWrapper<>();
                        groupQueryWrapper.eq("id_", classId);
                        List<ClassGroup> classGroups = classGroupService.list(groupQueryWrapper);
                        if (!CollectionUtils.isEmpty(classGroups)) {
                            List<String> className = classGroups.stream().map(ClassGroup::getName).collect(Collectors.toList());

                            teacherResp.setClassName(className);
                        }
                    }
                    teacherRespList.add(teacherResp);
                });
            }
        }
        response.setReturnCode(ReturnCodeEnum.CODE_200.getCode());
        response.setMessage(ReturnCodeEnum.CODE_200.getValue());
        response.setRecords(teacherRespList);
        response.setTotal(Math.toIntExact(teacherIPage.getTotal()));
        return response;
    }

    @Override
    public BaseResponse teacherDetail(TeacherReq req) {

        TeacherDetailResp teacherDetailResp = new TeacherDetailResp();
        if (req == null || req.getUserId() == null) {
            return BaseResponse.errorParam();
        }
        QueryWrapper<ClassGroupTeacherMapper> mapperQueryWrapper = new QueryWrapper<>();
        mapperQueryWrapper.eq("user_id_", req.getUserId());
        List<ClassGroupTeacherMapper> groupTeacherMapperList = classGroupTeacherMapperService.list(mapperQueryWrapper);

        if (!CollectionUtils.isEmpty(groupTeacherMapperList)) {
            List<Integer> classIds = groupTeacherMapperList.stream().map(ClassGroupTeacherMapper::getClassGroupId).collect(Collectors.toList());
            QueryWrapper<ClassGroup> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("id_", classIds);
            List<ClassGroup> classGroups = classGroupService.list(queryWrapper);
            if (!CollectionUtils.isEmpty(classGroups)) {
                List<ClassGroup> norClass = classGroups.stream().filter(e -> ClassGroupTypeEnum.NORMAL.getCode().equalsIgnoreCase(e.getType()) ||
                    ClassGroupTypeEnum.MIX.getCode().equalsIgnoreCase(e.getType()) || ClassGroupTypeEnum.HIGH.getCode().equalsIgnoreCase(e.getType())).collect(Collectors.toList());

                List<ClassGroup> vipClass = classGroups.stream().filter(e -> ClassGroupTypeEnum.VIP.getCode().equalsIgnoreCase(e.getType())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(norClass)) {
                    Integer norCount = norClass.stream().mapToInt(ClassGroup::getTotalClassTimes).sum();
                    teacherDetailResp.setGroupClassNum(norCount * norClass.size());
                }

                if (!CollectionUtils.isEmpty(vipClass)) {
                    Integer vipCount = vipClass.stream().mapToInt(ClassGroup::getTotalClassTimes).sum();
                    teacherDetailResp.setVipClassNum(vipCount * vipClass.size());
                }
                QueryWrapper<DemoGroup> demoGroupQueryWrapper = new QueryWrapper<>();
                demoGroupQueryWrapper.eq("user_id_", req.getUserId());
                List<DemoGroup> demoGroupList = demoGroupService.list(demoGroupQueryWrapper);
                if (!CollectionUtils.isEmpty(demoGroupList)) {
                    List<Long> demoId = demoGroupList.stream().map(e -> e.getId()).collect(Collectors.toList());
                    QueryWrapper<DemoGroupCoursesPlan> planQueryWrapper = new QueryWrapper<>();
                    planQueryWrapper.in("demo_group_id_", demoId);
                    List<DemoGroupCoursesPlan> demoGroupCoursesPlans = iDemoGroupCoursesPlanService.list(planQueryWrapper);
                    if (!CollectionUtils.isEmpty(demoGroupCoursesPlans)) {
                        Map<Date, List<DemoGroupCoursesPlan>> collect = demoGroupCoursesPlans.stream()
                            .collect(
                                Collectors.groupingBy(DemoGroupCoursesPlan::getCourseDate));


                        if (!CollectionUtils.isEmpty(collect)) {
                            List<TeacherDetailResp.InnerDemoGroup> innerDemoGroups = new ArrayList<>();
                            for (Date key : collect.keySet()) {
                                TeacherDetailResp.InnerDemoGroup demoGroup = new TeacherDetailResp.InnerDemoGroup();
                                demoGroup.setDateStr(DateUtil.date2String(key, DateUtil.DATE_FORMAT));
                                demoGroup.setWeek(DateUtil.date2Week(key));

                                List<DemoGroupCoursesPlan> demoGroupCoursesPlans1 = collect.get(key);
                                if (!CollectionUtils.isEmpty(demoGroupCoursesPlans1)) {
                                    List<TeacherDetailResp.DemoGroupPlan> planList = new ArrayList<>();
                                    demoGroupCoursesPlans1.forEach(e -> {
                                        TeacherDetailResp.DemoGroupPlan demoGroupPlan = new TeacherDetailResp.DemoGroupPlan();
                                        demoGroupPlan.setStartTime(DateUtil.date2String(e.getStartTime(), DateUtil.TIME_FORMAT));
                                        demoGroupPlan.setEndTime(DateUtil.date2String(e.getEndTime(), DateUtil.TIME_FORMAT));
                                        planList.add(demoGroupPlan);
                                    });
                                    demoGroup.setDemoGroupPlans(planList);
                                    innerDemoGroups.add(demoGroup);
                                }
                            }

                            QueryWrapper<CourseSchedule> scheduleQueryWrapper = new QueryWrapper<>();
                            scheduleQueryWrapper.eq("teacher_id_", req.getUserId());
                            scheduleQueryWrapper.eq("status_", CourseStatusEnum.OVER.getCode());
                            List<CourseSchedule> courseSchedules = courseScheduleService.list(scheduleQueryWrapper);
                            if (!CollectionUtils.isEmpty(courseSchedules)) {
                                teacherDetailResp.setUsed(courseSchedules.size());
                            } else {
                                teacherDetailResp.setUsed(0);
                            }

                            teacherDetailResp.setDemoGroups(innerDemoGroups);

                        }

                    }
                }

            }

            QueryWrapper<TeacherLeaveRecord> teacherLeaveRecordQueryWrapper = new QueryWrapper<>();
            teacherLeaveRecordQueryWrapper.eq("user_id_", req.getUserId());
            List<TeacherLeaveRecord> teacherLeaveRecordList = teacherLeaveRecordService.list(teacherLeaveRecordQueryWrapper);
            if (!CollectionUtils.isEmpty(teacherLeaveRecordList)) {
                AtomicReference<Integer> count = new AtomicReference<>(0);
                teacherLeaveRecordList.forEach(e -> {

                    Integer hour = DateUtil.subMin(e.getStartTime(), e.getEndTime());
                    if (hour != null) {
                        count.set(count.get() + hour);
                    }
                });
                teacherDetailResp.setCountNum(teacherLeaveRecordList.size());
                teacherDetailResp.setHourCount(count.get());
            }
        }
        return BaseResponse.success(teacherDetailResp);
    }

    @Override
    public PageResponse teacherVipClass(TeacherReq req) {

        PageResponse response = new PageResponse();
        if (req == null || req.getUserId() == null) {
            return PageResponse.errorParam();
        }

        IPage page = new Page(req.getPageNo() == null ? 1 : req.getPageNo(), req.getPageSize() == null ? 10 : req.getPageSize());
        QueryWrapper<VipGroup> vipGroupQueryWrapper = new QueryWrapper<>();
        vipGroupQueryWrapper.eq("user_id_", req.getUserId());
        IPage<VipGroup> vipGroupPage = vipGroupService.page(page, vipGroupQueryWrapper);

        List<VipGroup> vipGroupList = vipGroupPage.getRecords();
        List<VipGroupClassResp> vipGroupClassRespList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(vipGroupList)) {

            vipGroupList.forEach(e -> {
                VipGroupClassResp vipGroupClassResp = new VipGroupClassResp();
                vipGroupClassResp.setVipGroupName(e.getName());

                VipGroupCategory vipGroupCategory = vipGroupCategoryService.getById(e.getVipGroupCategoryId());
                if (vipGroupCategory != null) {
                    vipGroupClassResp.setVipClassType(vipGroupCategory.getName());
                }

                QueryWrapper<CourseSchedule> scheduleQueryWrapper = new QueryWrapper<>();
                scheduleQueryWrapper.eq("teacher_id_", req.getUserId());
                List<CourseSchedule> courseSchedules = courseScheduleService.list(scheduleQueryWrapper);
                if (!CollectionUtils.isEmpty(courseSchedules)) {
                    courseSchedules.forEach(c -> {
                        c.setClassDateStr(DateUtil.date2String(c.getClassDate(), DateUtil.DATE_FORMAT_EXTRA));

                    });
                    Map<String, List<CourseSchedule>> map = courseSchedules.stream().collect(Collectors.groupingBy(CourseSchedule::getClassDateStr));

                    if (!CollectionUtils.isEmpty(map)) {

                        int count1 = map.size();
                        int count2 = 0;
                        for (Map.Entry<String, List<CourseSchedule>> entry : map.entrySet()) {

                            if (!CollectionUtils.isEmpty(entry.getValue())) {
                                count2 = count2 + entry.getValue().size();
                            }

                        }
                        //月平均排課

                        if (count1 <= count2) {
                            vipGroupClassResp.setClassNum(1);
                        } else {

                            vipGroupClassResp.setClassNum(count2 % count1);
                        }

                    }
                    vipGroupClassRespList.add(vipGroupClassResp);
                }
            });
        }
        response.setTotal(Math.toIntExact(page.getTotal()));
        response.setRecords(vipGroupClassRespList);
        response.setReturnCode(ReturnCodeEnum.CODE_200.getCode());
        response.setMessage(ReturnCodeEnum.CODE_200.getValue());
        return response;
    }

    @Override
    public PageResponse dailySchedule(TeacherReq req) {
        Page<TeacherDailyScheduleResp> pageResult = new Page<>();
        if (Objects.isNull(req.getUserId())) {
            return PageResponse.errorParam();
        }
        List<TeacherDailyScheduleResp> list = Lists.newArrayList();
        Page<CourseSchedule> courseSchedulePage = new Page<CourseSchedule>(req.getPageNo(), req.getPageSize());
        QueryWrapper<CourseSchedule> courseScheduleQueryWrapper = new QueryWrapper<>();
        courseScheduleQueryWrapper.lambda().eq(CourseSchedule::getTeacherId, req.getUserId())
            .eq(Objects.nonNull(req.getDate()), CourseSchedule::getClassDate, req.getDate());
        IPage<CourseSchedule> page = courseScheduleService.page(courseSchedulePage, courseScheduleQueryWrapper);
        BeanUtils.copyProperties(page, pageResult);
        if (!CollectionUtils.isEmpty(page.getRecords())) {
            page.getRecords().forEach(courseSchedule -> {
                TeacherDailyScheduleResp teacherDailyScheduleResp = new TeacherDailyScheduleResp();
                teacherDailyScheduleResp.setCourseScheduleId(courseSchedule.getId())
                    .setCourseName(courseSchedule.getName())
                    .setCourseType(CourseSchedule.CourseScheduleType.getMsgByCode(courseSchedule.getType()));
                if (Objects.nonNull(courseSchedule.getStartClassTime()) && Objects.nonNull(courseSchedule.getEndClassTime())) {
                    teacherDailyScheduleResp.setClassTime(DateUtil.time2String(courseSchedule.getStartClassTime()) + "-" +
                        DateUtil.time2String(courseSchedule.getEndClassTime()));
                }
                QueryWrapper<TeacherAttendance> teacherAttendanceQueryWrapper = new QueryWrapper<>();
                teacherAttendanceQueryWrapper.lambda().eq(TeacherAttendance::getCourseScheduleId, courseSchedule.getId())
                    .eq(TeacherAttendance::getTeacherId, courseSchedule.getTeacherId())
                    .eq(TeacherAttendance::getClassGroupId, courseSchedule.getClassGroupId());
                TeacherAttendance teacherAttendance = teacherAttendanceService.getOne(teacherAttendanceQueryWrapper);
                Optional.ofNullable(teacherAttendance).ifPresent(attendance -> teacherDailyScheduleResp.setSignInStatus
                    (SignStatusEnum.getMsgByCode(attendance.getSignInStatus())));
                //考勤总人数
                QueryWrapper<StudentAttendance> totalQueryWrapper = new QueryWrapper<>();
                totalQueryWrapper.lambda().eq(StudentAttendance::getCourseScheduleId, courseSchedule.getId());
                int totalCount = studentAttendanceService.count(totalQueryWrapper);
                QueryWrapper<StudentAttendance> leaveWrapper = new QueryWrapper<>();
                //请假人数
                leaveWrapper.lambda().eq(StudentAttendance::getCourseScheduleId, courseSchedule.getId())
                    .eq(StudentAttendance::getStatus, StudentAttendanceStatusEnum.LEAVE.getCode());
                Integer leaveCount = studentAttendanceService.count(leaveWrapper);
                //已到人数
                QueryWrapper<StudentAttendance> normalWrapper = new QueryWrapper<>();
                normalWrapper.lambda().eq(StudentAttendance::getCourseScheduleId, courseSchedule.getId())
                    .eq(StudentAttendance::getStatus, StudentAttendanceStatusEnum.NORMAL.getCode());
                Integer normalCount = studentAttendanceService.count(normalWrapper);
                teacherDailyScheduleResp.setAttendanceRate(normalCount + "/" + totalCount)
                    .setLeaveNum(leaveCount);
                ClassGroup classGroup = classGroupService.getById(courseSchedule.getClassGroupId());
                if (Objects.nonNull(classGroup)) {
                    MusicGroup musicGroup = musicGroupService.getById(classGroup.getMusicGroupId());
                    if (Objects.nonNull(musicGroup)) {
                        School school = schoolService.getById(musicGroup.getSchoolId());
                        Optional.ofNullable(school).ifPresent(value -> teacherDailyScheduleResp.setSchoolName(value.getName()));
                    }
                }
                list.add(teacherDailyScheduleResp);
                pageResult.setRecords(list);
            });
        }
        return PageResponse.success(pageResult);
    }
}
