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

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.biz.dal.dao.ActivityEvaluationDao;
import com.yonge.cooleshow.biz.dal.dto.ActivityEvaluationDto;
import com.yonge.cooleshow.biz.dal.dto.activity.ActivityTeacherQuery;
import com.yonge.cooleshow.biz.dal.dto.search.ActivityEvaluationSearch;
import com.yonge.cooleshow.biz.dal.dto.search.MusicSheetSearch;
import com.yonge.cooleshow.biz.dal.entity.ActivityEvaluation;
import com.yonge.cooleshow.biz.dal.entity.ActivityPlan;
import com.yonge.cooleshow.biz.dal.entity.ActivityPlanReward;
import com.yonge.cooleshow.biz.dal.entity.Subject;
import com.yonge.cooleshow.biz.dal.enums.activity.ActivityRankingMethodEnum;
import com.yonge.cooleshow.biz.dal.service.ActivityEvaluationRecordService;
import com.yonge.cooleshow.biz.dal.service.ActivityEvaluationService;
import com.yonge.cooleshow.biz.dal.service.ActivityPlanRewardService;
import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
import com.yonge.cooleshow.biz.dal.service.SubjectService;
import com.yonge.cooleshow.biz.dal.support.WrapperUtil;
import com.yonge.cooleshow.biz.dal.vo.ActivityEvaluationVo;
import com.yonge.cooleshow.biz.dal.vo.ActivityMusicVo;
import com.yonge.cooleshow.biz.dal.vo.ActivityRankingVo;
import com.yonge.cooleshow.biz.dal.vo.MusicSheetVo;
import com.yonge.cooleshow.biz.dal.vo.activity.ActivityTeacherWrapper;
import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
import com.yonge.cooleshow.common.enums.ActivityResourceEnum;
import com.yonge.cooleshow.common.enums.ActivityTypeEnum;
import com.yonge.cooleshow.common.enums.EStatus;
import com.yonge.cooleshow.common.enums.YesOrNoEnum;
import com.yonge.toolset.base.exception.BizException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class ActivityEvaluationServiceImpl extends ServiceImpl<ActivityEvaluationDao, ActivityEvaluation> implements ActivityEvaluationService {

    @Autowired
    private ActivityPlanService activityPlanService;

    @Autowired
    private SubjectService subjectService;    

    @Autowired
    private ActivityEvaluationRecordService activityEvaluationRecordService;

    @Autowired
    private ActivityEvaluationService activityEvaluationService;

    @Autowired
    private ActivityPlanRewardService activityPlanRewardService;

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

    @Override
    public IPage<ActivityEvaluationVo> selectPage(IPage<ActivityEvaluationVo> page, ActivityEvaluationSearch query) {

        ActivityPlan activity = activityPlanService.getById(query.getActivityId());
        if (Objects.isNull(activity)) {
            throw new BizException("无效的活动ID");
        }

        List<ActivityEvaluationVo> evaluationInfos = baseMapper.selectPage(page, query);
        // 排序方式
        if (ActivityTypeEnum.EVALUATION == activity.getActivityType()
                && ActivityRankingMethodEnum.TOTAL_SCORE == activity.getRankingMethod()) {

            // 按声部聚合数据返回
            evaluationInfos = evaluationInfos.stream()
                    .collect(Collectors.groupingBy(x -> Long.parseLong(x.getSubjectId().split(",")[0])))
                    .entrySet().stream()
                    .sorted(Map.Entry.comparingByKey())
                    .flatMap(x -> x.getValue().stream())
                    .collect(Collectors.toList());

        }

        return page.setRecords(evaluationInfos);
    }

    @Override
    public List<ActivityEvaluationVo> selectAll(ActivityEvaluationSearch query) {
        return baseMapper.selectAll(query);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean addBatch(ActivityEvaluationDto param, SysUser user) {

        // 活动信息
        ActivityPlan activity = activityPlanService.getBaseMapper().selectById(param.getActivityId());
        if (Objects.isNull(activity)) {
            throw new BizException("无效的活动ID");
        }

        List<Long> activityContentIds = Lists.newArrayList();
        switch (activity.getActivityType()) {
            case EVALUATION: // 评测活动
                if (StringUtils.isEmpty(param.getMusicSheetIds())) {
                    throw new BizException("曲子id不能为空");
                }

                // 活动曲目ID
                activityContentIds = WrapperUtil.toLongList(param.getMusicSheetIds());
                break;
            case SHARE: // 分享活动
                if (StringUtils.isEmpty(param.getTeacherIds())) {
                    throw new BizException("老师ID不能为空");
                }

                // 活动关联老师ID
                activityContentIds = WrapperUtil.toLongList(param.getTeacherIds());
                break;
            case STANDARD_GIFT:
            default:
                break;
        }

        if (CollectionUtils.isEmpty(activityContentIds)) {
            // 活动内容请求ID为空，直接忽略后面业务逻辑流程
            return true;
        }

        List<ActivityEvaluation> activityEvaluations = baseMapper.selectList(Wrappers.<ActivityEvaluation>lambdaQuery()
                .eq(ActivityEvaluation::getActivityId, param.getActivityId())
        );

        // 活动类型
        ActivityTypeEnum activityType = ActivityTypeEnum.EVALUATION;
        String resourceType = ActivityResourceEnum.MUSIC_SHEET.getCode();

        if (Objects.nonNull(param.getActivityId())) {
            ActivityPlan activityPlan = activityPlanService.getBaseMapper().selectById(param.getActivityId());

            if (Objects.isNull(activityPlan)) {
                throw new BizException("当前活动ID无效");
            }
            activityType = activityPlan.getActivityType();

            switch (activityType) {
                case SHARE: // 活动分享老师
                    resourceType = ActivityResourceEnum.TEACHER.getCode();
                    break;
                case EVALUATION: // 曲目分享
                    resourceType = ActivityResourceEnum.MUSIC_SHEET.getCode();
                    break;
                default:
                    break;
            }
        }

        List<Long> oldMusicSheetIds = activityEvaluations.stream().map(ActivityEvaluation::getMusicSheetId).collect(Collectors.toList());
        activityContentIds.removeAll(oldMusicSheetIds);

        if ((oldMusicSheetIds.size() + activityContentIds.size()) > 10
                && activity.getRankingMethod() == ActivityRankingMethodEnum.MUSIC_RANKING
                && activityType == ActivityTypeEnum.EVALUATION) {
            // 评测活动、曲目排名需要限制曲目数量
            throw new BizException("添加的曲目不能多余10首");
        }
        if (CollectionUtils.isNotEmpty(activityContentIds)) {
            baseMapper.addBatch(param.getActivityId(), user.getId(), activityContentIds, resourceType);
            //更新修改人和修改时间
            activityPlanService.update(Wrappers.<ActivityPlan>lambdaUpdate()
                    .set(ActivityPlan::getUpdateBy, user.getId())
                    .eq(ActivityPlan::getId,param.getActivityId())
            );
        }

        // 更新评测活动奖品数
        if (ActivityTypeEnum.EVALUATION == activity.getActivityType()) {

            // 当前活动曲目数
            int ret = activityEvaluationService.count(Wrappers.<ActivityEvaluation>lambdaQuery()
                    .eq(ActivityEvaluation::getActivityId, activity.getId())
                    .eq(ActivityEvaluation::getResourceType, ActivityResourceEnum.MUSIC_SHEET));

            activityPlanRewardService.update(Wrappers.<ActivityPlanReward>lambdaUpdate()
                            .set(ActivityPlanReward::getRewardNum, ret)
                            .set(ActivityPlanReward::getRewardStock, ret)
                    .eq(ActivityPlanReward::getActivityId, activity.getId()));
        }

        return true;
    }


    @Override
    public List<ActivityMusicVo> getActivityMusic(Long activityPlanId, Long userId) {

        // 活动曲目信息
        List<ActivityMusicVo> result = baseMapper.selectActivityMusic(activityPlanId, userId);

        // 活动信息
        ActivityPlan activity = activityPlanService.getById(activityPlanId);
        if (Objects.isNull(activity)) {
            throw new BizException("无效的活动ID");
        }

        // 评测活动
        if (ActivityTypeEnum.EVALUATION == activity.getActivityType()) {


            // 单曲排名，计算每一个曲目的最高分
            if (ActivityRankingMethodEnum.MUSIC_RANKING == activity.getRankingMethod()) {

                result.parallelStream().forEach(item -> {

                    List<ActivityRankingVo> rankingList =  activityEvaluationRecordService.queryRankingList(activityPlanId, item.getEvaluationId(), 1);
                    if (rankingList != null && rankingList.size() > 0) {
                        item.setUserSubject(rankingList.get(0).getUserSubject());
                        item.setScore(rankingList.get(0).getScore());
                        item.setUserAvatar(rankingList.get(0).getUserAvatar());
                        item.setUsername(rankingList.get(0).getUsername());
                        item.setUserId(rankingList.get(0).getUserId());
                    }

                });

            }

            // 总分排名
            if (ActivityRankingMethodEnum.TOTAL_SCORE == activity.getRankingMethod()) {

                Map<Long, Double> collect = Maps.newHashMap();
                if (result.stream().anyMatch(x -> x.getJoin() == YesOrNoEnum.YES
                        && Objects.nonNull(userId))) {

                    collect = getBaseMapper().selectSubjectMusicHighestScoreStat(activity.getId(), userId).stream()
                            .collect(Collectors.toMap(StatGroupWrapper::getId, StatGroupWrapper::getNumber, (o, n) -> n));
                }

                for (ActivityMusicVo item : result) {

                    item.setScore(collect.getOrDefault(item.getEvaluationId(), 0D));
                }


            }

        }

        return result;
    }

    @Override
    public IPage<MusicSheetVo> musicPage(IPage<MusicSheetVo> page, MusicSheetSearch query) {
        return page.setRecords(baseMapper.musicPage(page, query));
    }

    /**
     * 活动老师信息
     *
     * @param page  ActivityTeacherWrapper
     * @param query ActivityTeacherQuery
     * @return IPage<ActivityTeacherWrapper>
     */
    @Override
    public IPage<ActivityTeacherWrapper> activityTeacherPageInfo(IPage<ActivityTeacherWrapper> page, ActivityTeacherQuery query) {

        // 排除存在时间冲突的已参加活动老师
        if (EStatus.ENABLE.match(query.getAddType())) {

            ActivityPlan activityPlan = activityPlanService.getBaseMapper().selectById(query.getActivityId());

            if (Objects.nonNull(activityPlan)) {

                // 排除存在时间冲突的老师
                query.activityType(ActivityTypeEnum.SHARE.getCode())
                        .resourceType(ActivityResourceEnum.TEACHER.getCode())
                        .activityState(EStatus.ENABLE.getValue())
                        .startTime(Optional.ofNullable(activityPlan.getActivityStart()).map(x -> x.getTime() / 1000).orElse(null))
                        .endTime(Optional.ofNullable(activityPlan.getActivityEnd()).map(x -> x.getTime() / 1000).orElse(null));
            }
        }

        List<ActivityTeacherWrapper> wrappers = baseMapper.selectActivityTeacherPageInfo(page, query);

        // 查询老师声部信息
        List<Long> subjectIds = wrappers.stream()
                .filter(x -> StringUtils.isNotEmpty(x.getSubjectId()))
                .flatMap(x -> Arrays.stream(x.getSubjectId().split(",")))
                .map(Long::parseLong).distinct().collect(Collectors.toList());

        Map<Long, String> subjectNameMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(subjectIds)) {

            subjectNameMap = subjectService.findBySubjectByIdList(subjectIds).stream()
                    .collect(Collectors.toMap(Subject::getId, Subject::getName, (o, n) -> n));
        }

        for (ActivityTeacherWrapper item : wrappers) {

            item.setSubjectName(subjectNameMap.entrySet().stream()
                    .filter(x -> item.getSubjectIds().contains(x.getKey()))
                    .map(Map.Entry::getValue)
                    .collect(Collectors.joining("、")));
        }

        return page.setRecords(wrappers);
    }

    /**
     * 按活动时间匹配老师信息
     *
     * @param page  IPage<ActivityTeacherWrapper>
     * @param query ActivityTeacherQuery
     * @return IPage<ActivityTeacherWrapper>
     */
    @Override
    public IPage<ActivityTeacherWrapper> activityTeacherByTimePageInfo(IPage<ActivityTeacherWrapper> page, ActivityTeacherQuery query) {

        // 按时间匹配老师时间
        List<ActivityTeacherWrapper> wrappers = baseMapper.selectActivityTeacherByTimePageInfo(page, query);

        return page.setRecords(wrappers);
    }

    /**
     * 批量更新评测曲目信息
     *
     * @param user SysUser
     * @param info ActivityEvaluationDto
     * @return int
     */
    @Transactional
    @Override
    public int batchUpdateEvaluationInfo(SysUser user, ActivityEvaluationDto info) {

        List<ActivityEvaluationDto.EvaluationInfo> evaluationInfos = info.getEvaluationInfos();

        List<ActivityEvaluation> evaluations = JSON.parseArray(JSON.toJSONString(evaluationInfos),
                ActivityEvaluation.class);

        // 批量更新
        activityEvaluationService.updateBatchById(evaluations, 30);

        return evaluationInfos.size();
    }

}