package com.yonge.cooleshow.biz.dal.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.biz.dal.dao.CourseHomeworkDao;
import com.yonge.cooleshow.biz.dal.dto.CourseHomeworkReviewDto;
import com.yonge.cooleshow.biz.dal.dto.CourseHomeworkSaveDto;
import com.yonge.cooleshow.biz.dal.dto.CourseHomeworkSubmitDto;
import com.yonge.cooleshow.biz.dal.dto.search.HomeworkAdminSearch;
import com.yonge.cooleshow.biz.dal.dto.search.HomeworkSearch;
import com.yonge.cooleshow.biz.dal.entity.CourseHomework;
import com.yonge.cooleshow.biz.dal.entity.CourseSchedule;
import com.yonge.cooleshow.biz.dal.entity.CourseScheduleStudentPayment;
import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
import com.yonge.cooleshow.biz.dal.enums.CourseScheduleEnum;
import com.yonge.cooleshow.biz.dal.enums.MessageTypeEnum;
import com.yonge.cooleshow.biz.dal.enums.YesOrNoEnum;
import com.yonge.cooleshow.biz.dal.service.*;
import com.yonge.cooleshow.biz.dal.vo.CourseHomeworkDetailVo;
import com.yonge.cooleshow.biz.dal.vo.CourseHomeworkVo;
import com.yonge.cooleshow.common.exception.BizException;
import com.yonge.toolset.thirdparty.message.MessageSenderPluginContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class CourseHomeworkServiceImpl extends ServiceImpl<CourseHomeworkDao, CourseHomework> implements CourseHomeworkService {

    @Autowired
    @Lazy
    private CourseScheduleService courseScheduleService;

    @Autowired
    private StudentCourseHomeworkService studentCourseHomeworkService;

    @Autowired
    private SysMessageService sysMessageService;

    @Autowired
    private SysUserFeignService sysUserFeignService;

    @Autowired
    private CourseScheduleStudentPaymentService courseScheduleStudentPaymentService;

	@Override
    public CourseHomeworkVo detail(Long id) {
        CourseHomeworkVo detail = baseMapper.detail(id);
        return detail;
    }
    
    @Override
    public IPage<CourseHomeworkVo> selectPage(IPage<CourseHomeworkVo> page, HomeworkSearch query){
        IPage<CourseHomeworkVo> courseHomeworkVoIPage = page.setRecords(baseMapper.selectPage(page, query));
        List<CourseHomeworkVo> records = courseHomeworkVoIPage.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return courseHomeworkVoIPage;
        }
        // 学生信息
        List<CourseHomeworkVo> studentInfoList = baseMapper.selectStudentInfo(records);

        // 旷课状态 和老师信息
        List<CourseHomeworkVo> teacherInfoList = baseMapper.selectTeacherInfo(records);

        // 声部信息
        List<CourseHomeworkVo> subjectList = baseMapper.selectSubjectInfoList(records);
        for (int i = 0; i < records.size(); i++) {
            records.get(i).setStudentId(studentInfoList.get(i).getStudentId());
            records.get(i).setStudentAvatar(studentInfoList.get(i).getStudentAvatar());
            records.get(i).setStudentName(studentInfoList.get(i).getStudentName());
            records.get(i).setSubjectName(subjectList.get(i).getSubjectName());
            records.get(i).setTeacherAvatar(teacherInfoList.get(i).getTeacherAvatar());
            records.get(i).setTeacherId(teacherInfoList.get(i).getTeacherId());
            records.get(i).setTeacherName(teacherInfoList.get(i).getTeacherName());
            records.get(i).setAbsenteeism(teacherInfoList.get(i).getAbsenteeism());
        }
        return courseHomeworkVoIPage;
    }

    @Override
    public CourseHomeworkDetailVo getCourseHomeworkDetailByCourseId(Long courseId) {

        // 课程基本信息
        CourseHomeworkDetailVo courseHomeworkDetailVo = baseMapper.selectCourseHomeworkDetailByCourseId(courseId);

        // 学生信息
        CourseHomeworkDetailVo studentInfoDetailVo = baseMapper
                .selectPaymentStudentInfo(courseHomeworkDetailVo.getCourseScheduleId());

        // 声部信息
        CourseHomeworkDetailVo subjectAndTeacherInfoVo = baseMapper
                .selectSubjectAndTeacherInfo(courseHomeworkDetailVo.getCourseGroupId());

        // 拼接数据
        courseHomeworkDetailVo.setStudentId(studentInfoDetailVo.getStudentId());
        courseHomeworkDetailVo.setStudentName(studentInfoDetailVo.getStudentName());
        courseHomeworkDetailVo.setStudentAvatar(studentInfoDetailVo.getStudentAvatar());
        courseHomeworkDetailVo.setSubjectName(subjectAndTeacherInfoVo.getSubjectName());
        courseHomeworkDetailVo.setTeacherId(subjectAndTeacherInfoVo.getTeacherId());
        courseHomeworkDetailVo.setTeacherAvatar(subjectAndTeacherInfoVo.getTeacherAvatar());
        courseHomeworkDetailVo.setTeacherName(subjectAndTeacherInfoVo.getTeacherName());
        return courseHomeworkDetailVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean decorateCourseHomework(CourseHomeworkSaveDto saveDto) {
        // 检查 老师 陪练课 课程状态为完成，有学生考勤记录 没有布置作业
        checkCourseSchedule(saveDto.getCourseScheduleId());

        // 检查已经布置了课后作业
        CourseHomework homework = checkHasHomework(saveDto.getCourseScheduleId());
        if (homework != null) {
            saveDto.setCourseHomeworkId(homework.getId());
        }

        CourseSchedule courseSchedule = courseScheduleService.getById(saveDto.getCourseScheduleId());
        // 创建课后作业
        CourseHomework courseHomework = getCourseHomework(saveDto, courseSchedule);

        boolean flag = this.saveOrUpdate(courseHomework);

        if (flag) {
            // 发送给学生 ->老师布置作业消息
            sendDecorateHomework(saveDto.getCourseScheduleId(), courseSchedule.getTeacherId());
        }
        return flag;

    }

    /**
     * 发送给学生 ->老师布置作业消息
     *
     * @param courseScheduleId 课程id
     * @param teacherId 老师id
     */
    private void sendDecorateHomework(Long courseScheduleId,Long teacherId) {
        CourseScheduleStudentPayment courseScheduleStudentPayment = courseScheduleStudentPaymentService.getByCourseId(
                courseScheduleId);
        SysUser student = sysUserFeignService.queryUserById(courseScheduleStudentPayment.getUserId());
        SysUser teacher = sysUserFeignService.queryUserById(teacherId);
        Map<Long,String> studentReceivers = new HashMap<>();
        studentReceivers.put(student.getId(), student.getPhone());
        // todo url设置
        sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.TEACHER_DECORATE_HOMEWORK, studentReceivers, null, 0,null , ClientEnum.STUDENT.getCode(),teacher.getUsername(),"url");
    }

    /**
     * 获取课程作业
     *
     * @param courseScheduleId 课程id
     * @return CourseHomework
     */
    private CourseHomework checkHasHomework(Long courseScheduleId) {
        List<CourseHomework> list = this.lambdaQuery()
                                        .eq(CourseHomework::getCourseScheduleId, courseScheduleId)
                                        .eq(CourseHomework::getCourseGroupType, CourseScheduleEnum.PRACTICE.getCode())
                                        .list();
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean reviewCourseHomework(CourseHomeworkReviewDto reviewDto) {
        // 检查 老师 陪练课 课程状态为完成，有学生考勤记录 没有布置作业
        checkCourseSchedule(reviewDto.getCourseScheduleId());

        // 检查已经布置了课后作业
        if (checkHasHomework(reviewDto.getCourseScheduleId()) == null) {
            throw new BizException("没布置作业，不能点评");
        }

        // 课程基本信息
        CourseHomeworkDetailVo courseHomeworkDetailVo = baseMapper
                .selectCourseHomeworkDetailByCourseId(reviewDto.getCourseScheduleId());

        // 检查学生是否提交作业
        if (!YesOrNoEnum.YES.getCode().equals(courseHomeworkDetailVo.getSubmitHomework().getCode())) {
            throw  new BizException("学生未提交作业，不能点评");
        }
        boolean flag = studentCourseHomeworkService.reviewCourseHome(courseHomeworkDetailVo.getStudentHomeworkId(),reviewDto.getReview());
        if (flag) {
             // 发送消息给学生  老师点评作业
            SysUser student = sysUserFeignService.queryUserById(courseHomeworkDetailVo.getStudentId());
            SysUser teacher = sysUserFeignService.queryUserById(courseHomeworkDetailVo.getTeacherId());
            Map<Long,String> studentReceivers = new HashMap<>();
            studentReceivers.put(student.getId(), student.getPhone());
            // todo url设置
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.TEACHER_REVIEW_HOMEWORK, studentReceivers, null, 0,null , ClientEnum.STUDENT.getCode(),teacher.getUsername(),"url");
        }
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitCourseHomework(CourseHomeworkSubmitDto submitDto) {
        // 检查 老师 陪练课 课程状态为完成，有学生考勤记录 没有布置作业
        checkCourseSchedule(submitDto.getCourseScheduleId());

        // 检查已经布置了课后作业
        if (checkHasHomework(submitDto.getCourseScheduleId()) == null) {
            throw new BizException("没布置作业，不能提交作业");
        }
        // 课程基本信息
        CourseHomeworkDetailVo courseHomeworkDetailVo = baseMapper
                .selectCourseHomeworkDetailByCourseId(submitDto.getCourseScheduleId());

        // 检查老师是否评价作业
        if (YesOrNoEnum.YES.getCode().equals(courseHomeworkDetailVo.getReviewHomework().getCode())) {
            throw  new BizException("老师已经点评作业，不能在提交");
        }
        boolean submitCourseHome = studentCourseHomeworkService
                .submitCourseHome(courseHomeworkDetailVo, submitDto.getSubmit(),submitDto.getStudentId());
        if (submitCourseHome) {
            CourseHomework courseHomework = this.getById(courseHomeworkDetailVo.getId());
            if (courseHomework.getCompletedNum() == null) {
                courseHomework.setCompletedNum(0);
            }
            courseHomework.setCompletedNum(courseHomework.getCompletedNum() + 1);
            this.updateById(courseHomework);

            // 发送学生提交作业消息给老师
            SysUser student = sysUserFeignService.queryUserById(courseHomeworkDetailVo.getStudentId());
            SysUser teacher = sysUserFeignService.queryUserById(courseHomeworkDetailVo.getTeacherId());
            Map<Long,String> receivers = new HashMap<>();
            receivers.put(teacher.getId(), teacher.getPhone());
            // todo url设置
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.STUDENT_SUBMIT_HOMEWORK, receivers, null, 0,null , ClientEnum.STUDENT.getCode(),student.getUsername(),"url");
            return true;

        } else {
            return false;
        }

    }

    @Override
    public IPage<CourseHomeworkVo> selectAdminPage(IPage<CourseHomeworkVo> page, HomeworkAdminSearch query) {
        IPage<CourseHomeworkVo> courseHomeworkVoIPage = page.setRecords(baseMapper.selectAdminPage(page, query));

        List<CourseHomeworkVo> records = courseHomeworkVoIPage.getRecords();
        List<Long> courseIdList = records
                      .stream()
                      .map(CourseHomeworkVo::getCourseId)
                      .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(courseIdList)) {
            return courseHomeworkVoIPage;
        }
        // 查询提交时间
        List<CourseHomeworkVo> courseHomeworkVoList = baseMapper.selectSubmitTime(courseIdList);
        for (int i = 0; i < records.size(); i++) {
            records.get(i).setSubmitTime(courseHomeworkVoList.get(i).getSubmitTime());
        }
        return courseHomeworkVoIPage;
    }

    /**
     * 检查课程能否布置作业
     *
     * @param courseScheduleId 课程id
     */
    private void checkCourseSchedule(Long courseScheduleId) {
        // 1. 检查课程类型
        CourseSchedule courseSchedule = courseScheduleService.getById(courseScheduleId);
        if (!CourseScheduleEnum.PRACTICE.getCode().equals(courseSchedule.getType())) {
            throw  new BizException("非陪练课，不能布置课后作业");
        }
        // 2. 检查课程结束
        if (!CourseScheduleEnum.COMPLETE.getCode().equals(courseSchedule.getStatus())) {
            throw  new BizException("课程未正常完成，不能布置课后作业");
        }
    }

    /**
     * 封装课程课后作业对象
     *
     * @param saveDto 课后作业信息
     * @param courseSchedule 课程信息
     * @return 课后作业对象
     */
    private CourseHomework getCourseHomework(CourseHomeworkSaveDto saveDto, CourseSchedule courseSchedule) {
        CourseHomework courseHomework = new CourseHomework();
        courseHomework.setId(saveDto.getCourseHomeworkId());
        courseHomework.setCourseGroupId(courseSchedule.getCourseGroupId());
        courseHomework.setCourseGroupType(CourseScheduleEnum.PRACTICE.getCode());
        courseHomework.setCourseScheduleId(saveDto.getCourseScheduleId());
        courseHomework.setTitle(saveDto.getTitle());
        courseHomework.setContent(saveDto.getContent());
        courseHomework.setAttachments(saveDto.getAttachments());
        courseHomework.setExpectNum(1);
        courseHomework.setCompletedNum(0);
        courseHomework.setCreateTime(new Date());
        return courseHomework;
    }

}