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

import java.math.BigDecimal;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yonge.cooleshow.biz.dal.dto.CourseMusicAlbumRelationDto;
import com.yonge.cooleshow.biz.dal.entity.CourseRelationMusicAlbum;
import com.yonge.cooleshow.biz.dal.entity.MusicAlbum;
import com.yonge.cooleshow.biz.dal.entity.MusicSheet;
import com.yonge.cooleshow.biz.dal.enums.course.RelationMusicAlbumEnum;
import com.yonge.cooleshow.biz.dal.service.CourseRelationMusicAlbumService;
import com.yonge.cooleshow.biz.dal.service.MusicAlbumService;
import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
import com.yonge.cooleshow.biz.dal.wrapper.course.CourseRelationWrapper;
import com.yonge.cooleshow.common.enums.YesOrNoEnum;
import org.apache.commons.collections.CollectionUtils;
import com.yonge.cooleshow.biz.dal.dto.VideoLessonGroupDetailDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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.VideoLessonGroupDao;
import com.yonge.cooleshow.biz.dal.dao.VideoLessonGroupDetailDao;
import com.yonge.cooleshow.biz.dal.dao.VideoLessonPurchaseRecordDao;
import com.yonge.cooleshow.biz.dal.dto.search.OrderSearch;
import com.yonge.cooleshow.biz.dal.dto.search.VideoLessonGroupSearch;
import com.yonge.cooleshow.biz.dal.dto.search.VideoLessonSearch;
import com.yonge.cooleshow.biz.dal.entity.Teacher;
import com.yonge.cooleshow.biz.dal.entity.VideoLessonGroup;
import com.yonge.cooleshow.biz.dal.entity.VideoLessonGroupDetail;
import com.yonge.cooleshow.biz.dal.entity.VideoLessonGroupLog;
import com.yonge.cooleshow.biz.dal.entity.VideoLessonPurchaseRecord;
import com.yonge.cooleshow.biz.dal.enums.GoodTypeEnum;
import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
import com.yonge.cooleshow.biz.dal.service.TeacherService;
import com.yonge.cooleshow.biz.dal.service.UserOrderService;
import com.yonge.cooleshow.biz.dal.service.VideoLessonGroupDetailService;
import com.yonge.cooleshow.biz.dal.service.VideoLessonGroupLogService;
import com.yonge.cooleshow.biz.dal.vo.UserOrderVo;
import com.yonge.cooleshow.biz.dal.vo.VideoLessonGroupDetailUpVo;
import com.yonge.cooleshow.biz.dal.vo.VideoLessonGroupDetailVo;
import com.yonge.cooleshow.biz.dal.vo.VideoLessonGroupUpVo;
import com.yonge.cooleshow.biz.dal.vo.VideoLessonGroupVo;
import com.yonge.cooleshow.biz.dal.vo.VideoLessonPurchaseStudent;
import com.yonge.cooleshow.biz.dal.vo.VideoLessonStudentVo;
import com.yonge.toolset.utils.json.JsonUtil;

/**
 * VideoLessonGroupDetailService服务实现类ø
 * @author yzp
 * @date 2022-03-26 00:01:38
 * @version v1.0
 **/
@Service
public class VideoLessonGroupDetailServiceImpl extends ServiceImpl<VideoLessonGroupDetailDao,VideoLessonGroupDetail> implements VideoLessonGroupDetailService {

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

    @Autowired
    private VideoLessonGroupDetailDao videoLessonGroupDetailDao;
    @Autowired
    private VideoLessonGroupDao videoLessonGroupDao;
    @Autowired
    private VideoLessonPurchaseRecordDao videoLessonPurchaseRecordDao;
    @Autowired
    private UserOrderService orderService;
    
    @Autowired
    private VideoLessonGroupLogService videoLessonGroupLogService;
    
    @Autowired
    private SysUserFeignService sysUserFeignService;

    @Autowired
    private TeacherService teacherService;
    @Autowired
    private CourseRelationMusicAlbumService courseRelationMusicAlbumService;
    @Autowired
    private MusicSheetService musicSheetService;
    @Autowired
    private MusicAlbumService musicAlbumService;

    public VideoLessonGroupDetailDao getDao() {
        return videoLessonGroupDetailDao;
    }

    /**
    * @Description: 查询视频课
    * @Author: cy
    * @Date: 2022/3/31
    */
    @Override
    public IPage<VideoLessonGroupDetailVo> selectPage(IPage<VideoLessonGroupDetailVo> page, VideoLessonSearch query) {
        return page.setRecords(baseMapper.selectPageAuth(page,query));
    }

    /**
    * @Description: 根据组id查询购买用户
    * @Author: cy
    * @Date: 2022/4/1
    */
    @Override
    public IPage<VideoLessonPurchaseStudent> selectPageStudent(IPage<VideoLessonPurchaseStudent> page, VideoLessonSearch query) {
        return page.setRecords(baseMapper.selectPageStudent(page,query));
    }

    /**
    * @Description: 新增视频课
    * @Author: cy
    * @Date: 2022/3/31
    */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertVideoLesson(List<VideoLessonGroupDetailDto> videoLessonList, SysUser sysUser) {
        Set<Long> synSet = Collections.synchronizedSet(new HashSet<>());
        for (VideoLessonGroupDetail detail : videoLessonList) {
            detail.setTeacherId(sysUser.getId());
            synSet.add(detail.getVideoLessonGroupId());
        }
        if (synSet.size()!=1){
            throw new RuntimeException("创建课程必须属于同组");
        }

        VideoLessonGroup lessonGroup = videoLessonGroupDao.selectById(synSet.iterator().next());
        if (lessonGroup==null){
            throw new RuntimeException("视频课组不存在");
        }

        //添加课程
        videoLessonGroupDetailDao.insertVideoLesson(videoLessonList);
        //刷新统计
        refreshLessonCount(synSet.iterator().next());
    }

    /**
    * @Description: 修改视频课
    * @Author: cy
    * @Date: 2022/3/31
    */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDetail(VideoLessonGroupDetailUpVo detailUpVo, SysUser sysUser) {
        //跟新课程
        detailUpVo.setUpdateBy(sysUser.getId());
        videoLessonGroupDetailDao.updateDetail(detailUpVo);

        //刷新统计
        if (detailUpVo.getVideoLessonGroupId()!=null){
            refreshLessonCount(detailUpVo.getVideoLessonGroupId());
        }
    }

    /**
    * @Description: 删除视频课
    * @Author: cy
    * @Date: 2022/3/31
    */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteDetail(Long id) {
        VideoLessonGroupDetail videoLessonDetail = videoLessonGroupDetailDao.selectById(id);
        if (videoLessonDetail !=null){
            videoLessonGroupDetailDao.deleteById(id);
            refreshLessonCount(videoLessonDetail.getVideoLessonGroupId());
        }
    }

    /**
    * @Description: 根据组id查询视频课&组信息-学生端
    * @Author: cy
    * @Date: 2022/4/2
    */
    @Override
    public VideoLessonStudentVo selectVideoLesson(Long groupId,Long userId) {
        VideoLessonStudentVo lessonStudentVo = new VideoLessonStudentVo();

        //校验课程是否购买

        //这里修改为，订单完成后才算购买过，待支付和支付中订单不算
        //因为页面再点击购买按钮时，会请求/userOrder/getPendingOrder接口，如果有支付中的订单，用户选择继续支付或取消订单
        OrderSearch param = new OrderSearch();
        param.setUserId(userId);
        param.setGoodType(GoodTypeEnum.VIDEO.getCode());
        param.setBizId(groupId);
        param.setStatus(OrderStatusEnum.PAID.getCode());
        List<UserOrderVo> userOrderVos = orderService.selectAllList(param);

        /*VideoLessonPurchaseRecord isAlreadyBuy= videoLessonPurchaseRecordDao.selectOne(Wrappers.<VideoLessonPurchaseRecord>lambdaQuery()
                .eq(VideoLessonPurchaseRecord::getStudentId, userId)
                .eq(VideoLessonPurchaseRecord::getVideoLessonGroupId, groupId));*/
        lessonStudentVo.setAlreadyBuy(!CollectionUtils.isEmpty(userOrderVos));

        VideoLessonGroupSearch query = new VideoLessonGroupSearch();
        //筛选已审核的视频课
        query.setGroupId(groupId);

        VideoLessonGroupVo videoLessonGroupVo = new VideoLessonGroupVo();
        VideoLessonGroupLog videoLessonGroupLog = videoLessonGroupLogService.queryLastestShelvesInfo(groupId);
        
        BeanUtils.copyProperties(videoLessonGroupLog, videoLessonGroupVo);
        
        videoLessonGroupVo.setId(videoLessonGroupLog.getVideoLessonGroupId());
        
        SysUser sysUser = sysUserFeignService.queryUserById(videoLessonGroupVo.getTeacherId());
        
        if(sysUser != null && sysUser.getId() != null){
        	videoLessonGroupVo.setUsername(sysUser.getUsername());
        	videoLessonGroupVo.setRealName(sysUser.getRealName());
        	videoLessonGroupVo.setAvatar(sysUser.getAvatar());
        }
        
        List<VideoLessonPurchaseRecord> videoLessonPurchaseRecordList = videoLessonPurchaseRecordDao.queryByVideoLessonGroupId(videoLessonGroupLog.getVideoLessonGroupId(), OrderStatusEnum.PAID.getCode());
        if (videoLessonGroupVo.getLessonPrice().compareTo(BigDecimal.ZERO) == 0) {
            VideoLessonGroup videoLessonGroup = videoLessonGroupDao.selectById(videoLessonGroupVo.getId());
            videoLessonGroupVo.setCountStudent(videoLessonPurchaseRecordList.size() + videoLessonGroup.getVirtualNumber());
        } else {
            videoLessonGroupVo.setCountStudent(videoLessonPurchaseRecordList.size());
        }

        Teacher teacher = teacherService.getById(videoLessonGroupVo.getTeacherId());
        if (teacher != null) {
            lessonStudentVo.setTeacherFlag(teacher.getTeacherFlag());
            lessonStudentVo.setDegreeFlag(teacher.getDegreeFlag());
        }
        lessonStudentVo.setLessonGroup(videoLessonGroupVo);

        VideoLessonSearch search = new VideoLessonSearch();
        search.setVideoLessonGroupId(groupId);
        lessonStudentVo.setDetailList(JsonUtil.parseArray(videoLessonGroupLog.getVideoDetailJson(), VideoLessonGroupDetailDto.class));

        List<CourseRelationMusicAlbum> recordInfos = lessonStudentVo.getDetailList().stream()
                .filter(x -> CollectionUtils.isNotEmpty(x.getCourseRelationMusicAlbumList()))
                .flatMap(x -> x.getCourseRelationMusicAlbumList().stream()).collect(Collectors.toList());
        // // 课程关联曲目、专辑信息
        // List<CourseRelationMusicAlbum> recordInfos = JSON.parseArray(JSON.toJSONString(relationMusicAlbums),
        //         CourseRelationMusicAlbum.class);

        List<CourseRelationWrapper.MusicAlbumInfo> musicAlbumInfos;
        if (CollectionUtils.isNotEmpty(recordInfos)) {

            musicAlbumInfos = getCourseRelationMusicAlbumInfos(recordInfos);

            // 填充课程关联曲目、专辑信息
            updateCourseRelationMusicAlbumInfo(lessonStudentVo.getDetailList(), musicAlbumInfos);
        }
        //lessonStudentVo.setMusicAlbumInfos(musicAlbumInfos);


        return lessonStudentVo;
    }

    /**
     * 填充课程关联曲目、专辑信息
     * @param lessonStudentVo VideoLessonStudentVo
     * @param musicAlbumInfos List<CourseRelationWrapper.MusicAlbumInfo>
     */
    @Override
    public void updateCourseRelationMusicAlbumInfo(List<VideoLessonGroupDetailDto> lessonStudentVo,
                                                   List<CourseRelationWrapper.MusicAlbumInfo> musicAlbumInfos) {

        Map<Long, List<CourseRelationWrapper.MusicAlbumInfo>> collect = musicAlbumInfos.stream()
                .collect(Collectors.groupingBy(CourseRelationWrapper.MusicAlbumInfo::getCourseId));

        if (CollectionUtils.isNotEmpty(lessonStudentVo)) {

            for (VideoLessonGroupDetailDto item : lessonStudentVo) {

                item.setMusicAlbumInfos(collect.getOrDefault(item.getId(), Lists.newArrayList()));
            }
        }
    }

    /**
     * 课程关联曲目/专辑信息
     * @param recordInfos
     * @return List<CourseRelationWrapper.MusicAlbumInfo>
     */
    @Override
    public List<CourseRelationWrapper.MusicAlbumInfo> getCourseRelationMusicAlbumInfos(List<CourseRelationMusicAlbum> recordInfos) {

        List<CourseRelationWrapper.MusicAlbumInfo> musicAlbumInfos = JSON.parseArray(JSON.toJSONString(recordInfos),
                CourseRelationWrapper.MusicAlbumInfo.class);

        // 分别查询曲目/专辑信息
        Map<String, List<Long>> collect = musicAlbumInfos.stream()
                .collect(Collectors.groupingBy(x -> x.getRelationType().getCode(),
                        Collectors.mapping(CourseRelationWrapper.MusicAlbumInfo::getMusicAlbumId, Collectors.toList())));

        Map<Long, MusicSheet> musicInfoMap = Maps.newHashMap();
        // 曲目信息
        if (collect.containsKey(RelationMusicAlbumEnum.MUSIC.name())) {

            List<Long> musicIds = collect.get(RelationMusicAlbumEnum.MUSIC.name());

            musicInfoMap = musicSheetService.listByIds(musicIds).stream()
                    .collect(Collectors.toMap(MusicSheet::getId, Function.identity(), (o, n) -> n));
        }

        Map<Long, MusicAlbum> albumInfoMap = Maps.newHashMap();
        // 专辑信息
        if (collect.containsKey(RelationMusicAlbumEnum.ALBUM.name())) {

            List<Long> albumIds = collect.get(RelationMusicAlbumEnum.ALBUM.name());

            albumInfoMap = musicAlbumService.listByIds(albumIds).stream()
                    .collect(Collectors.toMap(MusicAlbum::getId, Function.identity(), (o, n) -> n));
        }

        for (CourseRelationWrapper.MusicAlbumInfo item : musicAlbumInfos) {

            item.name("").cover("");
            if (RelationMusicAlbumEnum.MUSIC == item.getRelationType()
                    && musicInfoMap.containsKey(item.getMusicAlbumId())) {

                MusicSheet music = musicInfoMap.get(item.getMusicAlbumId());

                item.name(music.getMusicSheetName())
                        .cover(music.getTitleImg());
                item.setRemark(music.getComposer());
                item.setTagIds(music.getMusicTag());
                item.setStatus(music.getDelFlag()?YesOrNoEnum.NO:music.getState());
            }

            if (RelationMusicAlbumEnum.ALBUM == item.getRelationType()
                    && albumInfoMap.containsKey(item.getMusicAlbumId())) {

                MusicAlbum album = albumInfoMap.get(item.getMusicAlbumId());

                item.name(album.getAlbumName())
                        .cover(album.getAlbumCoverUrl());
                item.setRemark(album.getAlbumDesc());
                item.setTagIds(album.getAlbumTag());
                item.setStatus(album.getAlbumStatus());
            }
        }
        return musicAlbumInfos;
    }

    /**
    * @Description: 刷新组内lesson_count_
    * @Author: cy 
    * @Date: 2022/3/31 
    */
    public void refreshLessonCount(Long groupId){
        VideoLessonGroupUpVo groupUpVo = new VideoLessonGroupUpVo();
        groupUpVo.setId(groupId);
        videoLessonGroupDao.updateGroup(groupUpVo);
    }
}