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

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.microsvc.toolkit.common.webportal.exception.BizException;
import com.microsvc.toolkit.config.jwt.utils.JwtUserInfo;
import com.yonge.cooleshow.biz.dal.entity.*;
import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
import com.yonge.cooleshow.biz.dal.mapper.UserMusicMapper;
import com.yonge.cooleshow.biz.dal.service.*;
import com.yonge.cooleshow.biz.dal.wrapper.UserMusicStarWrapper;
import com.yonge.cooleshow.biz.dal.wrapper.UserMusicWrapper;
import com.yonge.cooleshow.common.constant.SysConfigConstant;
import com.yonge.cooleshow.common.enums.EUserMusicType;
import com.yonge.toolset.base.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户曲目作品
 * 2023-09-05 15:27:10
 */
@Slf4j
@Service
public class UserMusicServiceImpl extends ServiceImpl<UserMusicMapper, UserMusic> implements UserMusicService {



    @Autowired
    private UserMusicService userMusicService;

    @Autowired
    private SysMusicCompareRecordService sysMusicCompareRecordService;

    @Autowired
    private MusicSheetService musicSheetService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SubjectService subjectService;

    @Autowired
    private UserMusicStarService userMusicStarService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private TeacherService teacherService;

    @Autowired
    private UserMusicMapper userMusicMapper;


    /**
     * 查询详情
     * @param id 详情ID
     * @return UserMusic
     */
	@Override
    public UserMusic detail(Long id) {

        return baseMapper.selectById(id);
    }

    /**
     * 分页查询
     * @param page IPage<UserMusic>
     * @param query UserMusicWrapper.UserMusicQuery
     * @return IPage<UserMusic>
     */
    @Override
    public IPage<UserMusicWrapper.UserMusic> selectPage(IPage<UserMusicWrapper.UserMusic> page, UserMusicWrapper.UserMusicQuery query) {

        return page.setRecords(baseMapper.selectPage(page, query));
    }

    /**
     * 添加
     * @param userMusic UserMusicWrapper.UserMusic
     * @return Boolean
     */
    @Override
    public Boolean add(UserMusicWrapper.UserMusic userMusic) {

        return this.save(JSON.parseObject(userMusic.jsonString(), UserMusic.class));
    }

    /**
     * 更新
     * @param userMusic UserMusicWrapper.UserMusic
     * @return Boolean
     */
    @Override
    public Boolean update(UserMusicWrapper.UserMusic userMusic){

        return this.updateById(JSON.parseObject(userMusic.jsonString(), UserMusic.class));
    }


    /**
     *  根据曲目练习记录获取发布曲目
     *
     * @param musicPracticeRecordIds 曲目练习记录ID
     * @return
     */
    @Override
    public Map<Long, UserMusic> getMapByMusicPracticeRecordIds(List<Long> musicPracticeRecordIds) {
        if (CollectionUtils.isEmpty(musicPracticeRecordIds)) {
            return new HashMap<>();
        }
        List<UserMusic> list = this.lambdaQuery()
            .in(UserMusic::getMusicPracticeRecordId, musicPracticeRecordIds)
            .eq(UserMusic::getType, EUserMusicType.FORMAL)
            .eq(UserMusic::getDelFlag, false)
            .list();
        if (CollectionUtils.isEmpty(list)) {
            return new HashMap<>();
        }
        return list.stream().collect(java.util.stream.Collectors.toMap(UserMusic::getMusicPracticeRecordId, v -> v, (v1, v2) -> v1));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long save(UserMusicWrapper.AddUserMusic userMusic) {

        // 设置曲目ID
        if (userMusic.getMusicPracticeRecordId() != null) {
            SysMusicCompareRecord practiceRecord = sysMusicCompareRecordService.get(userMusic.getMusicPracticeRecordId());
            if (practiceRecord == null) {
                throw new BizException("练习记录不存在");
            }
            userMusic.setMusicSheetId(practiceRecord.getMusicSheetId());
            List<UserMusic> list = userMusicService.lambdaQuery()
                .eq(UserMusic::getMusicPracticeRecordId, userMusic.getMusicPracticeRecordId())
                .eq(UserMusic::getUserId, userMusic.getUserId())
                .eq(UserMusic::getClientType, userMusic.getClientType())
                .eq(UserMusic::getDelFlag, false)
                .orderByAsc(UserMusic::getId)
                .list();
            if (!CollectionUtils.isEmpty(list)) {
                userMusic.setId(list.get(0).getId());
            }
        }

        // 设置默认封面
        if (userMusic.getId() == null && StringUtils.isEmpty(userMusic.getImg()) && userMusic.getMusicSheetId() != null) {
            MusicSheet sheet = musicSheetService.getById(userMusic.getMusicSheetId());
            if (sheet != null) {
                userMusic.setImg(sheet.getTitleImg());
            }
        }
        // 设置视频默认封面
        if (userMusic.getId() == null && StringUtil.isEmpty(userMusic.getVideoImg())) {
            String value = sysConfigService.findConfigValue(SysConfigConstant.USER_MUSIC_VIDEO_DEFAULT_URL);
            userMusic.setVideoImg(value);
        }
        UserMusic entity = JSON.parseObject(JSON.toJSONString(userMusic), UserMusic.class);

        UserMusic old = null;
        if (entity.getId() != null) {
            old = userMusicService.getById(entity.getId());
            if (old.getType() == EUserMusicType.FORMAL && entity.getType() == EUserMusicType.DRAFT) {
                throw new BizException("已发布的作品不能修改为草稿");
            }
        }

        if (entity.getType() == null) {
        } else if (entity.getType().equals(EUserMusicType.DRAFT)) {
            entity.setSubmitTime(null);
        } else if (old == null || old.getType().equals(EUserMusicType.DRAFT)) {
            entity.setSubmitTime(new Date());
        }
        userMusicService.saveOrUpdate(entity);
        return entity.getId();
    }

    /**
     * 分页
     *
     */
    @Override
    public IPage<UserMusicWrapper.UserMusic> selectPage(IPage<UserMusicWrapper.UserMusic> page, UserMusicWrapper.UserMusicQuery query, JwtUserInfo<?> userInfo) {
        // 推荐作品 排序 同曲目同声部点赞降序>其他曲目同声部点赞降序
        if (query.getSort() !=null && query.getSort() == 1) {
            if (query.getExclusionId() != null) {
                UserMusic userMusic = userMusicService.getById(query.getExclusionId());
                if (userMusic != null) {
                    query.setClientType(userMusic.getClientType());
                    query.setUserId(userMusic.getUserId());
                }
            }
        }
        IPage<UserMusicWrapper.UserMusic> userMusicIPage = userMusicService.selectPage(page, query);
        List<UserMusicWrapper.UserMusic> records = userMusicIPage.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return userMusicIPage;
        }

        // id集合
        List<Long> ids = records.stream().map(UserMusicWrapper.UserMusic::getId).collect(Collectors.toList());

        // 是否点赞
        if (userInfo != null) {
            Map<Long, Boolean> starFlagMapByUserMusicIds = userMusicStarService.getStarFlagMapByUserMusicIds(ids, userInfo.getClientType(), userInfo.getUserId());
            for (UserMusicWrapper.UserMusic record : records) {
                Boolean starFlag = starFlagMapByUserMusicIds.get(record.getId());
                if (starFlag != null) {
                    record.setStarFlag(starFlag);
                }
            }
        }

        // 草稿过期时间
        SysConfig byParamName = sysConfigService.findByParamName(SysConfigConstant.USER_MUSIC_DRAFT_TIME);
        Integer time = 7;
        try {
            time = Integer.parseInt(byParamName.getParamName());
        }catch (Exception e){
            log.error("作品草稿过期时间配置错误");
        }

        for (UserMusicWrapper.UserMusic record : records) {
            if (record.getType() == EUserMusicType.DRAFT && record.getCreateTime() != null) {
                LocalDate localDate = record.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().plusDays(time);
                LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.MAX);
                record.setExpireTime(Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()));
            }
        }


        // 评测记录ID集合
        List<Long> musicPracticeRecordIds = records.stream()
            .map(UserMusicWrapper.UserMusic::getMusicPracticeRecordId).collect(Collectors.toList());
        Map<Long, SysMusicCompareRecord> recordMap = sysMusicCompareRecordService.getMapByIds(musicPracticeRecordIds);
        for (UserMusicWrapper.UserMusic record : records) {
            SysMusicCompareRecord musicPracticeRecord = recordMap.get(record.getMusicPracticeRecordId());
            if (musicPracticeRecord != null) {
                record.setRecordFilePath(musicPracticeRecord.getRecordFilePath());
                record.setVideoFilePath(musicPracticeRecord.getVideoFilePath());
            }
        }

        // 曲目ID集合
        List<Long> musicSheetIds = records.stream().map(UserMusicWrapper.UserMusic::getMusicSheetId).collect(Collectors.toList());
        Map<Long, MusicSheet> musicSheetMap = musicSheetService.getMapByIds(musicSheetIds);

        for (UserMusicWrapper.UserMusic record : records) {
            MusicSheet musicSheet = musicSheetMap.get(record.getMusicSheetId());
            if (musicSheet != null) {
                record.setMusicSheetName(musicSheet.getMusicSheetName());
                record.setMusicSheetSubjectId(musicSheet.getMusicSubject());
            }
        }

        // 用户ID集合

        // 学生ID集合
        List<Long> studentIds = records.stream().filter(o -> o.getClientType() == ClientEnum.STUDENT).map(UserMusicWrapper.UserMusic::getUserId).collect(Collectors.toList());

        Map<Long, Student> studentMap = studentService.getMapByIds(studentIds);


        // 老师ID集合
        List<Long> teacherIds = records.stream().filter(o -> o.getClientType() == ClientEnum.TEACHER).map(UserMusicWrapper.UserMusic::getUserId).collect(Collectors.toList());

        Map<Long, Teacher> teacherMap = teacherService.getMapByIds(teacherIds);
        studentIds.addAll(teacherIds);
        Map<Long, com.yonge.cooleshow.biz.dal.entity.SysUser> userMap = sysUserService.getMapByIds(studentIds);

        String teacherAvatar = sysConfigService.findConfigValue(SysConfigConstant.TEACHER_AVATAR);
        String studentAvatar = sysConfigService.findConfigValue(SysConfigConstant.STUDENT_AVATAR);


        for (UserMusicWrapper.UserMusic record : records) {
            SysUser sysUser = userMap.get(record.getUserId());
            if (sysUser != null) {
                record.setUsername(sysUser.getUsername());
                record.setAvatar(sysUser.getAvatar());
            }
            if (record.getClientType() == ClientEnum.STUDENT) {
                Student student = studentMap.get(record.getUserId());
                if (student != null) {

                    record.setSubjectId(student.getSubjectId());
                    record.setVipFlag(student.getMembershipEndTime() != null && student.getMembershipEndTime().after(new Date()));
                }
                if (StringUtil.isEmpty(record.getAvatar())) {
                    record.setAvatar(studentAvatar);
                }
            } else {
                Teacher teacher = teacherMap.get(record.getUserId());
                if (teacher != null) {
                    record.setSubjectId(teacher.getSubjectId());
                    record.setVipFlag(teacher.getMembershipEndTime() != null && teacher.getMembershipEndTime().after(new Date()));
                }
                if (StringUtil.isEmpty(record.getAvatar())) {
                    record.setAvatar(teacherAvatar);
                }
            }
        }

        // 声部ID集合
        List<String> subjectIds = records.stream().flatMap(o-> Lists.newArrayList(o.getSubjectId(),o.getMusicSheetSubjectId()).stream())
            .filter(o -> !StringUtil.isEmpty(o))
            .flatMap(o -> Arrays.stream(o.split(",")))
            .distinct().collect(Collectors.toList());

        Map<Integer, Subject> subjectMap =
            subjectService.getMapByIds(subjectIds);

        for (UserMusicWrapper.UserMusic record : records) {

            if (StringUtils.isNotBlank(record.getSubjectId())) {

                List<Integer> collect = Arrays.stream(record.getSubjectId().split(",")).map(Integer::parseInt).collect(Collectors.toList());
                List<Subject> subjects = new ArrayList<>();
                for (Integer integer : collect) {
                    Subject subject = subjectMap.get(integer);
                    if (subject != null) {
                        subjects.add(subject);
                    }
                }
                record.setSubjectName(subjects.stream().map(Subject::getName).collect(Collectors.joining(",")));

            }
            if (StringUtil.isEmpty(record.getMusicSheetSubjectId())) {
                continue;
            }
            String subjectName = Arrays.stream(record.getMusicSheetSubjectId().split(",")) // 1,2,3
                .map(Integer::parseInt)
                .map(subjectMap::get)
                .filter(Objects::nonNull)
                .map(Subject::getName)
                .collect(Collectors.joining(","));
            record.setMusicSheetSubjectName(subjectName);
        }


        return userMusicIPage;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void workOverdue() {
        String value = sysConfigService.findConfigValue(SysConfigConstant.USER_MUSIC_DRAFT_TIME);
        Integer time = 7;
        try {
            time = Integer.parseInt(value);
        }catch (Exception e){
            log.error("作品草稿过期时间配置错误");
        }
        userMusicMapper.workOverdue(time);
    }
}
