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

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yonge.cooleshow.biz.dal.dao.CourseScheduleDao;
import com.yonge.cooleshow.biz.dal.dao.StudentStarDao;
import com.yonge.cooleshow.biz.dal.dao.TeacherDao;
import com.yonge.cooleshow.biz.dal.entity.LiveRoom;
import com.yonge.cooleshow.biz.dal.entity.Teacher;
import com.yonge.cooleshow.biz.dal.enums.CacheNameEnum;
import com.yonge.cooleshow.biz.dal.service.LiveRoomService;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yonge.cooleshow.biz.dal.entity.TeacherTotal;
import com.yonge.cooleshow.biz.dal.vo.TeacherTotalVo;
import com.yonge.cooleshow.biz.dal.dto.search.TeacherTotalSearch;
import com.yonge.cooleshow.biz.dal.dao.TeacherTotalDao;
import com.yonge.cooleshow.biz.dal.service.TeacherTotalService;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;


@Service
public class TeacherTotalServiceImpl extends ServiceImpl<TeacherTotalDao, TeacherTotal> implements TeacherTotalService {
    private final static Logger log = LoggerFactory.getLogger(TeacherTotalServiceImpl.class);
    @Autowired
    private TeacherDao teacherDao;
    @Autowired
    private StudentStarDao studentStarDao;
    @Autowired
    private CourseScheduleDao courseScheduleDao;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private LiveRoomService liveRoomService;

    @Override
    public TeacherTotalVo detail(Long id) {
        return baseMapper.detail(id);
    }

    @Override
    public IPage<TeacherTotalVo> selectPage(IPage<TeacherTotalVo> page, TeacherTotalSearch query) {
        return page.setRecords(baseMapper.selectPage(page, query));
    }

    @Override
    public List<TeacherTotal> queryTeacherTotal() {
        List<Teacher> teachers = teacherDao.selectList(Wrappers.<Teacher>emptyWrapper()
                .select("userId"));
        //查询粉丝数
        List<TeacherTotalVo> teacherStarTotal = studentStarDao.queryTeacherTotal();
        Map<Long, TeacherTotalVo> teacherStarMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(teacherStarTotal)) {
            teacherStarMap = teacherStarTotal.stream().collect(Collectors.toMap(TeacherTotalVo::getUserId, o -> o));
        }
        //查询已上未上课时数
        List<TeacherTotalVo> teacherCourseTotal = courseScheduleDao.queryTeacherTotal();
        Map<Long, TeacherTotalVo> teacherCourseMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(teacherCourseTotal)) {
            teacherCourseMap = teacherCourseTotal.stream().collect(Collectors.toMap(TeacherTotalVo::getUserId, o -> o));
        }
        //查询老师正在直播的直播间
        List<LiveRoom> templist = liveRoomService.list(Wrappers.<LiveRoom>lambdaQuery()
                .eq(LiveRoom::getLiveState, 1)
                .eq(LiveRoom::getRoomState, 0)
                .eq(LiveRoom::getType, "TEMP"));

        Map<Long, Boolean> liveMap = new HashMap<>();
        for (LiveRoom liveRoom : templist) {
            liveMap.put(liveRoom.getSpeakerId(), true);
        }

        List<TeacherTotal> resultList = new ArrayList<>();
        for (Teacher teacher : teachers) {
            TeacherTotal teacherTotal = new TeacherTotal();
            teacherTotal.setUserId(teacher.getUserId());
            //粉丝数
            TeacherTotalVo fansTotal = teacherStarMap.get(teacher.getUserId());
            if (null != fansTotal && null != fansTotal.getFansNum()) {
                teacherTotal.setFansNum(fansTotal.getFansNum());
            }

            TeacherTotalVo courseTotal = teacherCourseMap.get(teacher.getUserId());
            if (null != courseTotal) {
                //课时数
                if (null != courseTotal.getExpTime()) {
                    teacherTotal.setExpTime(courseTotal.getExpTime());
                }
                if (null != courseTotal.getUnExpTime()) {
                    teacherTotal.setUnExpTime(courseTotal.getUnExpTime());
                }
                //星级
                Double starGrade = courseTotal.getStarGrade();
                if (null != starGrade) {
                    Long round = Math.round(starGrade);
                    teacherTotal.setStarGrade(round.doubleValue());
                }
            }
            //是否正在直播
            teacherTotal.setLiveFlag(null == liveMap.get(teacher.getUserId()) ? false : true);

            resultList.add(teacherTotal);
            redissonClient.getBucket(CacheNameEnum.TEACHER_TOTAL.getRedisKey(teacherTotal.getUserId()))
                    .set(teacherTotal);
        }
        //统计信息入库
        //批量入库
        saveOrUpdateBatch(resultList);
        return resultList;
    }

    int batchSize = 100;

    /***
     * 批量更新插入
     * @author liweifan
     * @param: resultList
     * @updateTime 2022/4/12 16:52
     */
    private void saveOrUpdateBatch(List<TeacherTotal> resultList) {
        List<TeacherTotal> teacherTotals = baseMapper.selectList(Wrappers.<TeacherTotal>emptyWrapper().select("userId"));
        Map<Long, TeacherTotal> teacherTotalMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(teacherTotals)) {
            teacherTotals.forEach(o -> teacherTotalMap.put(o.getUserId(), o));
        }
        //批量插入
        List<TeacherTotal> saveList = resultList.stream()
                .filter(o -> null == teacherTotalMap.get(o.getUserId())).collect(Collectors.toList());
        batchOpera(saveList, this::saveBatch);

        //批量更新
        List<TeacherTotal> updateList = resultList.stream()
                .filter(o -> null != teacherTotalMap.get(o.getUserId())).collect(Collectors.toList());
        batchOpera(updateList, this::updateBatch);
    }

    private void batchOpera(List<TeacherTotal> resultList, Consumer<List<TeacherTotal>> action) {
        int start = 0;
        while (true) {
            int end = start + batchSize;
            List<TeacherTotal> subList;
            if (resultList.size() > end) {
                subList = resultList.subList(start, start + batchSize);
            } else {
                subList = resultList.subList(start, resultList.size());
            }
            //处理sql
            action.accept(subList);
            if (end >= resultList.size()) {
                break;
            }
            start += batchSize;
        }
    }

    private void updateBatch(List<TeacherTotal> resultList) {
        for (TeacherTotal total : resultList) {
            updateById(total);
        }
    }

    @Override
    public Object getRedisValueByKey(String key) {
        return redissonClient.getBucket(key).get();
    }
}