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

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
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.MusicTagDao;
import com.yonge.cooleshow.biz.dal.dto.MusicTagSaveDto;
import com.yonge.cooleshow.biz.dal.dto.search.MusicTagSearch;
import com.yonge.cooleshow.biz.dal.entity.MusicTag;
import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
import com.yonge.cooleshow.biz.dal.service.MusicTagService;
import com.yonge.cooleshow.biz.dal.vo.MusicTagVo;
import com.yonge.cooleshow.common.enums.YesOrNoEnum;
import com.yonge.toolset.base.exception.BizException;
import jodd.util.StringUtil;
import org.springframework.beans.BeanUtils;
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.util.*;
import java.util.stream.Collectors;


@Service
public class MusicTagServiceImpl extends ServiceImpl<MusicTagDao, MusicTag> implements MusicTagService {


    @Autowired
    private MusicTagDao musicTagDao;

    @Autowired
    private SysUserFeignService sysUserFeignService;

    private MusicSheetService musicSheetService;

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

     @Override
    public IPage<MusicTagVo> selectPage(IPage<MusicTagVo> page, MusicTagSearch query){
         IPage<MusicTagVo> musicTagVoIPage = page.setRecords(baseMapper.selectPage(page, query));
         // 将父类的id 拿出来，集体查出子集
         List<Long> longList = musicTagVoIPage
                 .getRecords()
                 .stream()
                 .map(MusicTag::getId)
                 .collect(Collectors.toList());

         List<MusicTagVo> musicTagVoList = musicTagDao.getChildrenByParentIdList(longList,query.getState());

         // 根据父级id， 将子集分类
         Map<String, List<MusicTagVo>> musicTagMap = musicTagVoList.stream()
                                                                .collect(Collectors.groupingBy( vo -> vo.getParentTagId().toString()));
         musicTagVoIPage.getRecords()
                 .forEach(musicTagVo -> {
                     List<MusicTagVo> childrenList = musicTagMap.get(musicTagVo.getId().toString());
                     if (CollectionUtils.isEmpty(childrenList)) {
                         return;
                     }
                     childrenList.forEach(children -> {
                         musicTagVo.setEnablePlatformMusicSheetNum(musicTagVo.getEnablePlatformMusicSheetNum() + children.getEnablePlatformMusicSheetNum());
                         musicTagVo.setEnableTeacherMusicSheetNum(musicTagVo.getEnableTeacherMusicSheetNum() + children.getEnableTeacherMusicSheetNum());
                         musicTagVo.setMusicPlatformSheetNum(musicTagVo.getMusicPlatformSheetNum() + children.getMusicPlatformSheetNum());
                         musicTagVo.setMusicTeacherSheetNum(musicTagVo.getMusicTeacherSheetNum() + children.getMusicTeacherSheetNum());
                     });
                     // 如果没有按名称/编号查询 或 父级标签包含了名称/编号 ， 展示所有子集 标签列表子集收起
                     if (StringUtil.isBlank(query.getIdAndName())
                             || musicTagVo.getName().contains(query.getIdAndName())
                             || musicTagVo.getId().toString().contains(query.getIdAndName())) {
                         musicTagVo.setChildren(childrenList);
                     } else {
                         // 如果名称查询中，父级不包含名称/编号，子集包含，只展示包含的子集，并且默认展开子集列表
                         musicTagVo.setOpen(YesOrNoEnum.YES);
                         List<MusicTagVo> childrenNameList = childrenList.stream()
                                                                .filter(vo -> vo.getName().contains(query.getIdAndName())
                                                                        ||vo.getId().toString().contains(query.getIdAndName()))
                                                                .collect(Collectors.toList());
                         musicTagVo.setChildren(childrenNameList);
                     }
                 });
         return musicTagVoIPage;
     }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean del(Long musicTagId) {

        // 有关联的曲目或专辑不让删除
        if (checkTagBeUsed(musicTagId)) {
            throw  new BizException("当前标签或子集标签已被使用，不可删除");
        }

        // 删除下面的子集标签
        return this.lambdaUpdate()
                   .eq(MusicTag::getParentTagId,musicTagId)
                   .or(wrapper -> wrapper.eq(MusicTag::getId,musicTagId))
                   .set(MusicTag::getDelFlag,true)
                   .update();

    }

    /**
     * 检查标签是否被使用过
     *
     * @param musicTagId 标签id
     * @return
     */
    private boolean checkTagBeUsed(Long musicTagId) {

        List<MusicTag> list = this.lambdaQuery()
                                  .eq(MusicTag::getParentTagId, musicTagId)
                                  .eq(MusicTag::getDelFlag, false)
                                  .list();
        List<Long> longs = list.stream().map(MusicTag::getId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(longs)) {
            longs = new ArrayList<>();
        }
        longs.add(musicTagId);
        if (baseMapper.checkTagBeUsedMusicAblum(longs) >0) return true;
        if (baseMapper.checkTagBeUsedMusicSheet(longs) >0) return true;

        return false;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean state(Long musicTagId) {
        MusicTag tag = this.getById(musicTagId);
        if (Objects.isNull(tag)) {
            throw new BizException("标签信息不存在");
        }
        MusicTag musicTag = new MusicTag();
        musicTag.setId(musicTagId);
        if (tag.getState().getCode().equals(YesOrNoEnum.NO.getCode())) {
            musicTag.setState(YesOrNoEnum.YES);
            return this.updateById(musicTag);
        } else {
            // 一级停用，二级也停用
            if (musicTag.getParentTagId() == null || musicTag.getParentTagId() ==0) {
                return this.lambdaUpdate()
                    .eq(MusicTag::getParentTagId,musicTagId)
                    .or(wrapper -> wrapper.eq(MusicTag::getId,musicTagId))
                    .set(MusicTag::getState,YesOrNoEnum.NO)
                    .update();
            } else {
                musicTag.setState(YesOrNoEnum.NO);
                return this.updateById(musicTag);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createMusicTag(MusicTagSaveDto musicTagSaveDto) {

        if (checkNameRepeat(musicTagSaveDto.getName(), musicTagSaveDto.getId())) {
            throw new BizException("标签名称重复");
        }

        SysUser sysUser = sysUserFeignService.queryUserInfo();
        MusicTag musicTag = new MusicTag();
        musicTag.setDelFlag(false);
        musicTag.setState(YesOrNoEnum.NO);
        if (musicTagSaveDto.getParentTagId() == null) {
            musicTag.setParentTagId(0L);
        } else {
            musicTag.setParentTagId(musicTagSaveDto.getParentTagId());
        }
        musicTag.setName(musicTagSaveDto.getName());
        musicTag.setCreateTime(new Date());
        musicTag.setUpdateTime(new Date());
        musicTag.setCreateBy(sysUser.getId());
        musicTag.setUpdateBy(sysUser.getId());
        return this.save(musicTag);
    }

    /**
     * 检查标签名称重复
     *
     * @param name 名称
     * @param id 标签id， 更新
     * @return boolean
     */
    private boolean checkNameRepeat(String name,Long id) {
        LambdaQueryChainWrapper<MusicTag> eq = this.lambdaQuery()
                                                   .eq(MusicTag::getDelFlag, YesOrNoEnum.NO.getCode())
                                                   .eq(MusicTag::getName, name);
        if (id != null) {
            eq.ne(MusicTag::getId,id);
        }
        return eq.count() != 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMusicTag(MusicTagSaveDto musicTagSaveDto) {

        if (checkNameRepeat(musicTagSaveDto.getName(), musicTagSaveDto.getId())) {
            throw new BizException("标签名称重复");
        }
        MusicTag oldTag = super.getById(musicTagSaveDto.getId());
        if (YesOrNoEnum.YES.getCode().equals(oldTag.getState().getCode())) {
            throw new BizException("启用状态下不能修改");
        }

        SysUser sysUser = sysUserFeignService.queryUserInfo();
        MusicTag musicTag = new MusicTag();
        musicTag.setDelFlag(false);
        musicTag.setId(musicTagSaveDto.getId());
        if (musicTagSaveDto.getParentTagId() == null) {
            musicTag.setParentTagId(0L);
        } else {
            musicTag.setParentTagId(musicTagSaveDto.getParentTagId());
        }
        musicTag.setName(musicTagSaveDto.getName());
        musicTag.setUpdateTime(new Date());
        musicTag.setUpdateBy(sysUser.getId());
        return this.updateById(musicTag);
    }

    @Override
    public List<MusicTagVo> selectMusicTagTree() {
        List<MusicTag> list = this.lambdaQuery()
                .eq(MusicTag::getDelFlag,YesOrNoEnum.NO.getCode())
                .eq(MusicTag::getState,YesOrNoEnum.YES.getCode())
                .list();
        if (list == null) {
            return new ArrayList<>();
        }
        List<MusicTagVo> musicTagVoList = list.stream().map(musicTag -> {
            MusicTagVo musicTagVo = new MusicTagVo();
            BeanUtils.copyProperties(musicTag, musicTagVo);
            return musicTagVo;
        }).collect(Collectors.toList());

        List<MusicTagVo> tree = new ArrayList<>();
        for (MusicTagVo musicTagVo : musicTagVoList) {
            if (musicTagVo.getParentTagId() == null || musicTagVo.getParentTagId() == 0) {
                tree.add(musicTagVo);
            }
            for (MusicTagVo tagVo : musicTagVoList) {
                if (tagVo.getParentTagId() != null && tagVo.getParentTagId() != 0
                        && tagVo.getParentTagId().equals(musicTagVo.getId())) {
                    if (musicTagVo.getChildren() == null) {
                        musicTagVo.setChildren(new ArrayList<>());
                    }
                    musicTagVo.getChildren().add(tagVo);
                }
            }
        }
        return tree;
    }

    @Override
    public boolean checkParentDifferent(List<Long> musicTagIdList) {

        if (CollectionUtils.isEmpty(musicTagIdList)) {
            return true;
        }
        List<MusicTag> list = this.lambdaQuery().in(MusicTag::getId, musicTagIdList).list();
        return list.size() == musicTagIdList.size();

    }

    @Override
    public String getMusicTagNames(List<Long> tagIdList) {

        if (CollectionUtils.isEmpty(tagIdList)) {
            return "";
        }
        List<MusicTag> list = this.lambdaQuery()
                                  .in(MusicTag::getId, tagIdList)
                                    .eq(MusicTag::getDelFlag,YesOrNoEnum.NO)
                                  .list();
        if (CollectionUtils.isEmpty(list)) {
            return "";
        }
        return list.stream().map(MusicTag::getName).collect(Collectors.joining(","));
    }


}