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.CourseScheduleHomeworkSearch;
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.entity.ImGroup;
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.service.*;
import com.yonge.cooleshow.biz.dal.wordfilter.WordFilter;
import com.yonge.cooleshow.common.constant.SysConfigConstant;
import com.yonge.cooleshow.common.enums.YesOrNoEnum;
import com.yonge.toolset.mybatis.support.PageUtil;
import com.yonge.cooleshow.biz.dal.vo.CourseHomeworkDetailVo;
import com.yonge.cooleshow.biz.dal.vo.CourseHomeworkVo;
import com.yonge.cooleshow.biz.dal.vo.CourseScheduleHomeworkVo;
import com.yonge.cooleshow.biz.dal.vo.StudentHomeworkVo;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.thirdparty.message.MessageSenderPluginContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;


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

    private static final Logger log = LoggerFactory.getLogger(CourseHomeworkServiceImpl.class);

    @Autowired
    @Lazy
    private CourseScheduleService courseScheduleService;

    @Autowired
    private StudentCourseHomeworkService studentCourseHomeworkService;

    @Autowired
    private SysMessageService sysMessageService;

    @Autowired
    private SysUserFeignService sysUserFeignService;

    @Autowired
    private ImGroupService imGroupService;

    @Autowired
    private CourseScheduleStudentPaymentService courseScheduleStudentPaymentService;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private WordFilter wordFilter;

	@Override
    public CourseHomeworkVo detail(Long id) {
        return baseMapper.detail(id);
    }
    
    @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<Long> practiceRecordIdList = records.stream()
                .filter(courseHomeworkVo -> courseHomeworkVo.getType().getCode().equals(CourseScheduleEnum.PRACTICE.getCode()))
                .map(CourseHomeworkVo::getCourseId)
                .collect(Collectors.toList());

        List<Long> recordIdList = records.stream()
                                                 .map(CourseHomeworkVo::getCourseId)
                                                 .collect(Collectors.toList());

        // 学生信息 陪练课展示
        List<CourseHomeworkVo> studentInfoList;
        if (CollectionUtils.isEmpty(practiceRecordIdList)) {
            studentInfoList = new ArrayList<>();
        } else{
            studentInfoList = baseMapper.selectStudentInfo(practiceRecordIdList);
        }
        if (CollectionUtils.isEmpty(studentInfoList)) {
            studentInfoList = new ArrayList<>();
        }
        Map<Long, List<CourseHomeworkVo>> studentCollect = studentInfoList.stream()
                .collect(Collectors.groupingBy( CourseHomeworkVo::getCourseId));

        // 老师信息
        List<CourseHomeworkVo> teacherInfoList = baseMapper.selectTeacherInfo(recordIdList);
        if (CollectionUtils.isEmpty(teacherInfoList)) {
            teacherInfoList = new ArrayList<>();
        }
        Map<Long, List<CourseHomeworkVo>> teacherCollect = teacherInfoList.stream()
                      .collect(Collectors.groupingBy( CourseHomeworkVo::getCourseId));

        // 旷课状态  学生端展示
        Map<Long, List<CourseHomeworkVo>> absenteeismCollect = new HashMap<>();
        if (query.getStudentId() != null) {
            List<CourseHomeworkVo> absenteeismList = baseMapper.selectAbsenteeism(practiceRecordIdList,query.getStudentId());
            if (CollectionUtils.isEmpty(absenteeismList)) {
                absenteeismList = new ArrayList<>();
            }
            absenteeismCollect = absenteeismList.stream().collect(Collectors.groupingBy( CourseHomeworkVo::getCourseId));
        }


        // 声部信息 群组 课程信息
        List<CourseHomeworkVo> subjectList = baseMapper.selectSubjectAndGroupInfoList(recordIdList);

        if (CollectionUtils.isEmpty(subjectList)) {
            subjectList = new ArrayList<>();
        }
        Map<Long, List<CourseHomeworkVo>> subjectCollect = subjectList.stream()
                      .collect(Collectors.groupingBy( CourseHomeworkVo::getCourseId));

        for (CourseHomeworkVo record : records) {
            List<CourseHomeworkVo> courseHomeworkVoList = studentCollect.get(record.getCourseId());
            CourseHomeworkVo courseHomeworkVo;
            if (!CollectionUtils.isEmpty(courseHomeworkVoList)) {
                courseHomeworkVo = courseHomeworkVoList.get(0);
                record.setStudentId(courseHomeworkVo.getStudentId());
                record.setStudentAvatar(courseHomeworkVo.getStudentAvatar());
                record.setStudentName(courseHomeworkVo.getStudentName());
            }
            courseHomeworkVoList = teacherCollect.get(record.getCourseId());
            if (!CollectionUtils.isEmpty(courseHomeworkVoList)) {
                courseHomeworkVo = courseHomeworkVoList.get(0);
                record.setTeacherId(courseHomeworkVo.getTeacherId());
                record.setTeacherName(courseHomeworkVo.getTeacherName());
                record.setTeacherAvatar(courseHomeworkVo.getTeacherAvatar());
            }
            courseHomeworkVoList = absenteeismCollect.get(record.getCourseId());
            if (!CollectionUtils.isEmpty(courseHomeworkVoList)) {
                courseHomeworkVo = courseHomeworkVoList.get(0);
                record.setAbsenteeism(courseHomeworkVo.getAbsenteeism());
            } else {
                record.setAbsenteeism(YesOrNoEnum.NO);
            }
            courseHomeworkVoList = subjectCollect.get(record.getCourseId());
            if (!CollectionUtils.isEmpty(courseHomeworkVoList)) {
                courseHomeworkVo = courseHomeworkVoList.get(0);
                record.setCourseGroupName(courseHomeworkVo.getCourseGroupName());
                record.setSubjectName(courseHomeworkVo.getSubjectName());
                record.setClassNum(courseHomeworkVo.getClassNum());
                record.setImGroupId(courseHomeworkVo.getImGroupId());
            }
        }
        return courseHomeworkVoIPage;
    }

    @Override
    public CourseHomeworkDetailVo getCourseHomeworkDetailByCourseId(Long courseId, Long studentId) {

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

        if (courseHomeworkDetailVo == null) {
            throw  new BizException("未找到作业信息");
        }

        // 课程组的群聊
        ImGroup imGroup = imGroupService.getByCourseGroupId(courseHomeworkDetailVo.getCourseGroupId());
        if (imGroup != null) {
            courseHomeworkDetailVo.setImGroupId(imGroup.getId());
        }

        // 购买人数
        List<CourseScheduleStudentPayment> studentPaymentList = courseScheduleStudentPaymentService.getByCourseId(
                courseHomeworkDetailVo.getCourseScheduleId());
        if (!CollectionUtils.isEmpty(studentPaymentList)) {
            courseHomeworkDetailVo.setStudentNum(studentPaymentList.size());
        }

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

        // 声部信息
        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) {
            // 发送给学生 ->老师布置作业消息
            try {
                sendDecorateHomework(saveDto.getCourseScheduleId(), courseSchedule.getTeacherId());
            } catch (Exception e) {
                log.warn("老师布置作业信息发送失败，{}",e.getMessage());
            }
        }
        return flag;

    }

    /**
     * 发送给学生 ->老师布置作业消息
     *
     * @param courseScheduleId 课程id
     * @param teacherId 老师id
     */
    private void sendDecorateHomework(Long courseScheduleId,Long teacherId) {
        List<CourseScheduleStudentPayment> paymentList = courseScheduleStudentPaymentService.getByCourseId(
                courseScheduleId);
        if (paymentList.isEmpty()) {
            return;
        }
        SysUser teacher = sysUserFeignService.queryUserById(teacherId);
        String url = sysMessageService.selectConfigUrl(MessageTypeEnum.TEACHER_DECORATE_HOMEWORK.getCode(),courseScheduleId);
        for (CourseScheduleStudentPayment courseScheduleStudentPayment : paymentList) {
            SysUser student = sysUserFeignService.queryUserById(courseScheduleStudentPayment.getUserId());
            Map<Long,String> studentReceivers = new HashMap<>();
            studentReceivers.put(student.getId(), student.getPhone());

            try {
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum
                       .TEACHER_DECORATE_HOMEWORK,studentReceivers, null, 0,url ,
                       ClientEnum.STUDENT.getCode(),teacher.getUsername());
            } catch (Exception e) {
                log.warn("老师布置作业消息发送失败  学生id：{}",student.getId());
            }
        }
    }

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean reviewCourseHomework(CourseHomeworkReviewDto reviewDto) {
        if (wordFilter.include(reviewDto.getReview(), 3)) {
            throw new BizException("文本包含敏感信息");
        }
        // 检查 老师 陪练课 课程状态为完成，有学生考勤记录 没有布置作业
        checkCourseSchedule(reviewDto.getCourseScheduleId());
        // 检查已经布置了课后作业
        if (checkHasHomework(reviewDto.getCourseScheduleId()) == null) {
            throw new BizException("没布置作业，不能点评");
        }

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

        // 检查学生是否提交作业
        if (!YesOrNoEnum.YES.getCode().equals(courseHomeworkDetailVo.getSubmitHomework().getCode())) {
            throw  new BizException("学生未提交作业，不能点评");
        }
        boolean flag = studentCourseHomeworkService.reviewCourseHome(courseHomeworkDetailVo.getStudentHomeworkId(),reviewDto.getReview());
        if (flag) {
             // 发送消息给学生  老师点评作业
            try {
                sendReviewMessage(reviewDto, courseHomeworkDetailVo);
            } catch (Exception e) {
                log.warn("老师点评作业消息发送失败，{}",e.getMessage());
            }
        }
        return flag;
    }

    // 发送老师点评信息
    private void sendReviewMessage(CourseHomeworkReviewDto reviewDto, CourseHomeworkDetailVo courseHomeworkDetailVo) {
        SysUser student = sysUserFeignService.queryUserById(courseHomeworkDetailVo.getStudentId());
        SysUser teacher = sysUserFeignService.queryUserById(courseHomeworkDetailVo.getTeacherId());
        Map<Long,String> studentReceivers = new HashMap<>();
        studentReceivers.put(student.getId(), student.getPhone());
        String url = sysMessageService.selectConfigUrl(MessageTypeEnum.TEACHER_REVIEW_HOMEWORK.getCode(),reviewDto.getCourseScheduleId());
        sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.TEACHER_REVIEW_HOMEWORK,
        studentReceivers, null, 0, url , ClientEnum.STUDENT.getCode(), teacher.getUsername());
    }

    @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(), submitDto.getStudentId(),getHomeworkExpireTime());

        // 检查老师是否评价作业
        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);

            try {
                sendSubmitMessage(submitDto, courseHomeworkDetailVo);
            }catch (Exception e) {
                log.warn("学生提交作业消息发送失败，{}",e.getMessage());
            }
            return true;

        } else {
            return false;
        }

    }

    private String getHomeworkExpireTime() {

        String homeworkExpireTime = sysConfigService.findConfigValue(SysConfigConstant.HOMEWORK_EXPIRE_TIME);
        if (StringUtils.isEmpty(homeworkExpireTime)) {
            return "9999";
        }
        return homeworkExpireTime;
    }

    //  发送学生提交作业消息
    private void sendSubmitMessage(CourseHomeworkSubmitDto submitDto, CourseHomeworkDetailVo courseHomeworkDetailVo) {
        // 发送学生提交作业消息给老师
        SysUser student = sysUserFeignService.queryUserById(submitDto.getStudentId());
        SysUser teacher = sysUserFeignService.queryUserById(courseHomeworkDetailVo.getTeacherId());
        Map<Long,String> receivers = new HashMap<>();
        receivers.put(teacher.getId(), teacher.getPhone());

        String url = sysMessageService.selectConfigUrl(MessageTypeEnum.STUDENT_SUBMIT_HOMEWORK.getCode(),submitDto.getCourseScheduleId(),student.getId());
        sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.STUDENT_SUBMIT_HOMEWORK,
        receivers, null, 0, url, ClientEnum.TEACHER.getCode(), student.getUsername());
    }

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

    @Override
    public CourseScheduleHomeworkVo getCourseHomeworkDetailByCourseId(CourseScheduleHomeworkSearch query) {
        //  查询课程作业信息
        CourseScheduleHomeworkVo courseScheduleHomeworkVo = baseMapper
                .selectCourseHomeworkByCourseId(query.getCourseId());
        if (courseScheduleHomeworkVo == null) {
            return new CourseScheduleHomeworkVo();
        }
        // 课程组的群聊
        ImGroup imGroup = imGroupService.getByCourseGroupId(courseScheduleHomeworkVo.getCourseGroupId());
        if (imGroup != null) {
            courseScheduleHomeworkVo.setImGroupId(imGroup.getId());
        }

        // 课程人员作业
        IPage<StudentHomeworkVo> studentHomeworkList = baseMapper
                .selectStudentHomeworkByCourseId(PageUtil.getPage(query),query.getCourseId());

        courseScheduleHomeworkVo.setCourseGroupName(courseScheduleHomeworkVo.getCourseGroupName() + "-第" + courseScheduleHomeworkVo.getClassNum() + "课");

        courseScheduleHomeworkVo.setStudentHomeworkList(studentHomeworkList);
        courseScheduleHomeworkVo.setStudentNum(studentHomeworkList.getTotal());
        return courseScheduleHomeworkVo;

    }

    /**
     * 检查课程能否布置作业
     *
     * @param courseScheduleId 课程id
     */
    private void checkCourseSchedule(Long courseScheduleId) {
        // 1. 检查课程类型
        CourseSchedule courseSchedule = courseScheduleService.getById(courseScheduleId);
        if (!CourseScheduleEnum.PRACTICE.getCode().equals(courseSchedule.getType())
                && !CourseScheduleEnum.PIANO_ROOM_CLASS.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(courseSchedule.getType());
        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;
    }

}