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


import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.BasicUserDto;
import com.ym.mec.biz.dal.entity.ClassGroup;
import com.ym.mec.biz.dal.entity.CourseScheduleEvaluate;
import com.ym.mec.biz.dal.entity.PracticeGroup;
import com.ym.mec.biz.dal.entity.Subject;
import com.ym.mec.biz.dal.enums.MessageTypeEnum;
import com.ym.mec.biz.service.CourseScheduleEvaluateService;
import com.ym.mec.biz.service.SysConfigService;
import com.ym.mec.biz.service.SysMessageService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.redis.service.RedisCache;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.util.date.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

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


@Service
public class CourseScheduleEvaluateServiceImpl extends BaseServiceImpl<Long, CourseScheduleEvaluate> implements CourseScheduleEvaluateService {

    @Autowired
    private CourseScheduleEvaluateDao courseScheduleEvaluateDao;
    @Autowired
    private ClassGroupDao classGroupDao;
    @Autowired
    private TeacherDao teacherDao;
    @Autowired
    private PracticeGroupDao practiceGroupDao;
    @Autowired
    private RedisCache<String, Object> redisCache;
    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private SysConfigDao sysConfigDao;
    @Autowired
    private SubjectDao subjectDao;

    @Override
    public BaseDAO<Long, CourseScheduleEvaluate> getDAO() {
        return courseScheduleEvaluateDao;
    }


    @Override
    public boolean addStudyReport(CourseScheduleEvaluate courseScheduleEvaluate) {
        ClassGroup classGroup = classGroupDao.get(courseScheduleEvaluate.getClassGroupId());
        if (classGroup == null) {
            throw new BizException("课程不存在！");
        }
        String lockKey = "study_report_" + classGroup.getId();
        if (!redisCache.getLocked(lockKey, 1, 10)) {
            throw new BizException("报告提交中，请稍等");
        }
        try {
            CourseScheduleEvaluate hasOne = courseScheduleEvaluateDao.findByClassGroupId(courseScheduleEvaluate.getClassGroupId());
            if (hasOne != null) {
                throw new BizException("报告已添加，请勿重复提交");
            }
            Integer classGroupCourseTimes = courseScheduleEvaluateDao.getClassGroupCourseTimes(classGroup.getId());
            Date date = new Date();
            courseScheduleEvaluate.setTimes(classGroupCourseTimes);
            courseScheduleEvaluate.setTotalMinutes(classGroupCourseTimes * 25);
            courseScheduleEvaluate.setMusicGroupId(classGroup.getMusicGroupId());
            courseScheduleEvaluate.setCreateTime(date);
            courseScheduleEvaluate.setUpdateTime(date);
            courseScheduleEvaluate.setStatus(1);
            courseScheduleEvaluate.setVersion(1);
            long num = courseScheduleEvaluateDao.insert(courseScheduleEvaluate);
            if (num <= 0) {
                throw new BizException("报告添加失败，请重试");
            }
        } finally {
            redisCache.releaseLocked(lockKey, 1);
        }
        return true;
    }

    @Override
    public CourseScheduleEvaluate getStudyReport(Integer classGroupId) {
        CourseScheduleEvaluate studyReport = courseScheduleEvaluateDao.findByClassGroupId(classGroupId);
        if (studyReport == null) {
            throw new BizException("报告不存在");
        }
        SysUser user = teacherDao.getUser(studyReport.getStudentId());
        BasicUserDto teacherInfo = teacherDao.findTeacherInfo(studyReport.getTeacherId());
        studyReport.setStudent(user);
        studyReport.setTeacher(teacherInfo);
        long practiceGroupId = Long.parseLong(studyReport.getMusicGroupId());
        PracticeGroup practiceGroup = practiceGroupDao.get(practiceGroupId);
        ClassGroup classGroup = classGroupDao.get(studyReport.getClassGroupId());
        studyReport.setTimes(classGroup.getTotalClassTimes());
        studyReport.setTotalMinutes(classGroup.getTotalClassTimes() * practiceGroup.getSingleClassMinutes());
        return studyReport;

    }

    @Override
    public List<CourseScheduleEvaluate> findByGroupId(Integer groupId, Integer status) {
        return courseScheduleEvaluateDao.findByGroupId(groupId, status);
    }

    @Override
    public CourseScheduleEvaluate findById(Integer id) {
        CourseScheduleEvaluate studyReport = courseScheduleEvaluateDao.findById(id);
        if (studyReport == null) {
            throw new BizException("报告不存在");
        }
        SysUser user = teacherDao.getUser(studyReport.getStudentId());
        BasicUserDto teacherInfo = teacherDao.findTeacherInfo(studyReport.getTeacherId());
        studyReport.setStudent(user);
        studyReport.setTeacher(teacherInfo);
        return studyReport;
    }

    @Override
    public List<CourseScheduleEvaluate> getNeedPostList(Integer teacherId) {
        return courseScheduleEvaluateDao.getNeedPostReports(teacherId);
    }

    @Override
    public List<CourseScheduleEvaluate> createEvaluate(Date nowDate) {
        Date startDate = DateUtil.trunc(nowDate);
        Date afterDate = DateUtil.addDays(DateUtil.getLastSecondWithDay(nowDate), 5);
        boolean afterDateIsLastDay = DateUtil.isSameDay(DateUtil.getLastDayOfMonth(startDate), afterDate);

        List<CourseScheduleEvaluate> needPostReportPracticeGroups = practiceGroupDao.getNeedPostReportPracticeGroups(startDate, afterDate, afterDateIsLastDay);

        Map<Integer, Integer> courseTimesMap = new HashMap<>();
        Map<Integer, Integer> reportCountMap = new HashMap<>();
        Map<Integer, String> subjectMap = new HashMap<>();
        if (needPostReportPracticeGroups.size() > 0) {
            Date courseStartDate = DateUtil.addMonths(startDate, -1);
            List<Integer> classGroupIds = needPostReportPracticeGroups.stream().map(CourseScheduleEvaluate::getClassGroupId).collect(Collectors.toList());
            List<ClassGroup> reportCourseTimes = practiceGroupDao.getReportCourseTimes(classGroupIds, courseStartDate, startDate);
            courseTimesMap = reportCourseTimes.stream().collect(Collectors.toMap(ClassGroup::getId, ClassGroup::getTotalClassTimes));

            List<CourseScheduleEvaluate> courseScheduleEvaluates = courseScheduleEvaluateDao.hasReportList(classGroupIds, startDate);
            if (courseScheduleEvaluates.size() > 0) {
                reportCountMap = courseScheduleEvaluates.stream().collect(Collectors.toMap(CourseScheduleEvaluate::getClassGroupId, CourseScheduleEvaluate::getTimes));
            }
            List<Integer> subjectIds = needPostReportPracticeGroups.stream().map(CourseScheduleEvaluate::getSubjectId).collect(Collectors.toList());
            List<Subject> subjects = subjectDao.findBySubjectIds(subjectIds);
            subjectMap = subjects.stream().collect(Collectors.toMap(Subject::getId, Subject::getName));
        }
        Iterator<CourseScheduleEvaluate> iterator = needPostReportPracticeGroups.iterator();
        while (iterator.hasNext()) {
            CourseScheduleEvaluate courseScheduleEvaluate = iterator.next();
            if (subjectMap.get(courseScheduleEvaluate.getSubjectId()).contains("钢琴")) {
                iterator.remove();
                continue;
            }

            if (reportCountMap.containsKey(courseScheduleEvaluate.getClassGroupId()) &&
                    reportCountMap.get(courseScheduleEvaluate.getClassGroupId()) > 0) {
                iterator.remove();
                continue;
            }
            int times = 0;
            if (courseTimesMap.containsKey(courseScheduleEvaluate.getClassGroupId()) &&
                    courseTimesMap.get(courseScheduleEvaluate.getClassGroupId()) != null
            ) {
                times = courseTimesMap.get(courseScheduleEvaluate.getClassGroupId());
            }
            courseScheduleEvaluate.setTimes(times);
            courseScheduleEvaluate.setTotalMinutes(times * courseScheduleEvaluate.getTotalMinutes());
            courseScheduleEvaluate.setCreateTime(nowDate);
            courseScheduleEvaluate.setUpdateTime(nowDate);
            courseScheduleEvaluate.setStatus(0);
            courseScheduleEvaluate.setVersion(2);
        }

        if (needPostReportPracticeGroups.size() > 0) {
            courseScheduleEvaluateDao.batchAdd(needPostReportPracticeGroups);
        }
        return needPostReportPracticeGroups;
    }

    @Override
    public boolean updateStudyReport(CourseScheduleEvaluate courseScheduleEvaluate) {
        CourseScheduleEvaluate evaluate = courseScheduleEvaluateDao.get(courseScheduleEvaluate.getId());
        if (evaluate == null) {
            throw new BizException("课程不存在！");
        }
        evaluate.setUpdateTime(new Date());
        evaluate.setStatus(1);
        evaluate.setMusicTheory(courseScheduleEvaluate.getMusicTheory());
        evaluate.setSong(courseScheduleEvaluate.getSong());
        evaluate.setTeachingMaterial(courseScheduleEvaluate.getTeachingMaterial());
        evaluate.setItem(courseScheduleEvaluate.getItem());
        evaluate.setComment(courseScheduleEvaluate.getComment());
        long num = courseScheduleEvaluateDao.update(evaluate);
        if (num <= 0) {
            throw new BizException("报告添加失败，请重试");
        }
        return true;
    }

    @Override
    public void pushNeedPostReport() {
        List<CourseScheduleEvaluate> needPostReports = courseScheduleEvaluateDao.getNeedPostReports(null);
        if (needPostReports.size() == 0) {
            return;
        }
        Map<Integer, List<CourseScheduleEvaluate>> teacherEvaluates = needPostReports.stream().collect(Collectors.groupingBy(CourseScheduleEvaluate::getTeacherId));
        String teacherBaseUrl = sysConfigDao.findConfigValue(SysConfigService.TEACHER_BASE_URL);

        String pushUrl = teacherBaseUrl + "/#/tobeReport";
        Map<Integer, String> userMap = new HashMap<>();
        for (Map.Entry<Integer, List<CourseScheduleEvaluate>> integerListEntry : teacherEvaluates.entrySet()) {
            userMap.put(integerListEntry.getKey(), integerListEntry.getKey().toString());
        }

        sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.NEED_POST_STUDY_REPORT,
                userMap, null, 0, "8?" + pushUrl, "TEACHER");

    }
}
