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

import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
import com.yonge.cooleshow.biz.dal.vo.ActivityPlanVo;
import com.yonge.cooleshow.biz.dal.vo.ShareProfitVo;
import com.yonge.cooleshow.biz.dal.dao.AlbumMusicRelateDao;
import com.yonge.cooleshow.biz.dal.dao.MusicSheetDao;
import com.yonge.cooleshow.biz.dal.dao.MusicSheetPurchaseRecordDao;
import com.yonge.cooleshow.biz.dal.entity.MusicSheetPurchaseRecord;
import com.yonge.cooleshow.biz.dal.enums.ChargeTypeEnum;
import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
import com.yonge.cooleshow.biz.dal.enums.album.PurchaseRecordTypeEnum;
import com.yonge.cooleshow.biz.dal.service.MusicSheetPurchaseRecordService;
import com.yonge.cooleshow.biz.dal.wrapper.StatGroupWrapper;
import com.yonge.cooleshow.common.enums.ActivityShareEnum;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.additional.query.impl.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yonge.cooleshow.biz.dal.dao.MusicAlbumDao;
import com.yonge.cooleshow.biz.dal.dto.MusicAlbumSheetDto;
import com.yonge.cooleshow.biz.dal.dto.MusicAlbumSheetSortDto;
import com.yonge.cooleshow.biz.dal.dto.search.MusicAlbumDetailSearch;
import com.yonge.cooleshow.biz.dal.dto.search.MusicAlbumSearch;
import com.yonge.cooleshow.biz.dal.dto.search.StudentMusicAlbumSearch;
import com.yonge.cooleshow.biz.dal.entity.AlbumFavorite;
import com.yonge.cooleshow.biz.dal.entity.AlbumMusicRelate;
import com.yonge.cooleshow.biz.dal.entity.MusicAlbum;
import com.yonge.cooleshow.biz.dal.service.AlbumFavoriteService;
import com.yonge.cooleshow.biz.dal.service.AlbumMusicRelateService;
import com.yonge.cooleshow.biz.dal.service.MusicAlbumService;
import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
import com.yonge.cooleshow.biz.dal.service.MusicTagService;
import com.yonge.cooleshow.biz.dal.vo.AlbumDetailVo;
import com.yonge.cooleshow.biz.dal.vo.MusicAlbumVo;
import com.yonge.cooleshow.biz.dal.vo.MusicSheetVo;
import com.yonge.cooleshow.common.enums.YesOrNoEnum;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.base.util.StringUtil;
import com.yonge.toolset.mybatis.support.PageUtil;

/**
 * MusicAlbumService服务实现类
 * @author yzp
 * @date 2022-03-26 00:01:37
 * @version v1.0
 **/
@Service
public class MusicAlbumServiceImpl extends ServiceImpl<MusicAlbumDao,MusicAlbum> implements MusicAlbumService {

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

    @Autowired
    private ActivityPlanService activityPlanService;
    @Autowired
    private MusicAlbumDao musicAlbumDao;

    @Autowired
    private AlbumMusicRelateService albumMusicRelateService;

    @Autowired
    private MusicSheetService musicSheetService;

    @Autowired
    private MusicTagService musicTagService;

    @Autowired
    private AlbumFavoriteService albumFavoriteService;
    @Autowired
    private MusicSheetPurchaseRecordDao musicSheetPurchaseRecordMapper;
    @Autowired
    private MusicSheetDao musicSheetMapper;
    @Autowired
    private AlbumMusicRelateDao albumMusicRelateMapper;

    @Autowired
    private MusicSheetPurchaseRecordService musicSheetPurchaseRecordService;

    public MusicAlbumDao getDao() {
        return musicAlbumDao;
    }

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean state(Long id) {
        MusicAlbum musicAlbum = this.getById(id);
        if (musicAlbum == null) {
            throw  new BizException("未找到专辑信息");
        }
        if (YesOrNoEnum.NO.getCode().equals(musicAlbum.getAlbumStatus().getCode())) {
            musicAlbum.setAlbumStatus(YesOrNoEnum.YES);
        } else {
            musicAlbum.setAlbumStatus(YesOrNoEnum.NO);
        }
        return this.updateById(musicAlbum);
    }

    @Override
    public AlbumDetailVo detail(IPage<MusicSheetVo> page, MusicAlbumDetailSearch query, SysUser sysUser, ClientEnum client) {
        MusicAlbumVo musicAlbum = baseMapper.selectMusicAlbumById(query.getId());
        if (musicAlbum == null) {
            throw  new BizException("未找到专辑信息");
        }
        AlbumDetailVo albumDetailVo = new AlbumDetailVo();
        albumDetailVo.setId(musicAlbum.getId());
        albumDetailVo.setAlbumName(musicAlbum.getAlbumName());
        albumDetailVo.setAlbumDesc(musicAlbum.getAlbumDesc());
        albumDetailVo.setAlbumTag(musicAlbum.getAlbumTag());
        albumDetailVo.setAlbumCoverUrl(musicAlbum.getAlbumCoverUrl());
        albumDetailVo.setAlbumStatue(musicAlbum.getAlbumStatus());
        albumDetailVo.setAlbumFavoriteCount(musicAlbum.getAlbumFavoriteCount());
        albumDetailVo.setAlbumPrice(musicAlbum.getAlbumPrice());
        albumDetailVo.setPaymentType(musicAlbum.getPaymentType());
        albumDetailVo.setMusicTagNames(musicTagService.getMusicTagNames(StringUtil.toLongList(musicAlbum.getAlbumTag())));

        // 新增专辑曲目查询条件
        if (query.getType() != null && query.getType() == 1) {
            query.setSubjectIds(musicAlbum.getSubjectId());

            // 判断专辑收费类型；非免费类型，只能添加平台曲目
            /*if (!ChargeTypeEnum.FREE.match(musicAlbum.getPaymentType())) {

                // 曲目来源
                query.setSourceType(SourceTypeEnum.PLATFORM);
                // 曲目收费类型
                if (musicAlbum.getPaymentType().contains(",")) {
                    // 多种付费方式
                    query.setPaymentTypes(Lists.newArrayList(musicAlbum.getPaymentType(), ChargeTypeEnum.FREE.getCode()));
                } else {
                    // 单一付费方式
                    query.setChargeType(ChargeTypeEnum.valueOf(musicAlbum.getPaymentType()));
                }

            }*/
        }

        IPage<MusicSheetVo> musicSheetVoIPage = musicSheetService.selectAlbumDetailPage(page,query);

        List<MusicSheetVo> records = musicSheetVoIPage.getRecords();
        if (CollectionUtils.isNotEmpty(records)) {

            // 专辑曲目付费方式
            List<String> paymentTypes = musicSheetVoIPage.getRecords().stream()
                    .flatMap(x -> Arrays.stream(x.getPaymentType().split(","))).distinct().collect(Collectors.toList());
            albumDetailVo.setMusicPaymentTypes(paymentTypes);

            // 更新曲目专辑数量
            musicSheetService.updateMusicAlbumNumInfo(records);
        }


        albumDetailVo.setMusicSheetList(PageUtil.pageInfo(musicSheetVoIPage));

        albumDetailVo.setMusicSheetCount((int) musicSheetVoIPage.getTotal());

        if (sysUser == null) {
            return albumDetailVo;
        }

        // 查询购买信息
        MusicSheetPurchaseRecord purchaseRecord = musicSheetPurchaseRecordService.checkPurchase(
                sysUser.getId(), query.getId(), client, PurchaseRecordTypeEnum.ALBUM);
        if (purchaseRecord != null) {
            albumDetailVo.setOrderStatus(purchaseRecord.getOrderStatus());
            albumDetailVo.setOrderNo(purchaseRecord.getOrderNo());
        }

        return albumDetailVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delMusicSheet(Long albumId, String musicSheetIds) {
        MusicAlbum musicAlbum = this.getById(albumId);
        if (musicAlbum == null) {
            throw  new BizException("未找到专辑信息");
        }

        // 付费专辑，需要校验是否已存在购买记录
        /*if (!ChargeTypeEnum.VIP.match(musicAlbum.getPaymentType())) {

            // 统计付费专辑的购买数量
            Integer count = musicSheetPurchaseRecordMapper.selectCount(Wrappers.<MusicSheetPurchaseRecord>lambdaQuery()
                    .eq(MusicSheetPurchaseRecord::getMusicSheetId, albumId)
                    .eq(MusicSheetPurchaseRecord::getPurchaseType, PurchaseRecordTypeEnum.ALBUM)
            );
            if (Optional.ofNullable(count).orElse(0) > 0) {
                throw new BizException("当前专辑已有购买记录");
            }
        }*/

        List<Long> musicSheetIdList = StringUtil.toLongList(musicSheetIds);
        return albumMusicRelateService.delMusicSheet(albumId,musicSheetIdList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addMusicSheet(Long albumId, List<MusicAlbumSheetDto.AlbumMusic> albumMusicList, Long userId) {
        MusicAlbum musicAlbum = this.getById(albumId);
        if (musicAlbum == null) {
            throw  new BizException("未找到专辑信息");
        }

        // 付费专辑最多只能添加两首免费曲目
        /*if (!ChargeTypeEnum.FREE.match(musicAlbum.getPaymentType())) {

            // 新添加曲目统计
            long freeNum = 0;
            List<Long> musicIds = albumMusicList.stream()
                    .map(MusicAlbumSheetDto.AlbumMusic::getMusicSheetId).distinct().collect(Collectors.toList());

            if (CollectionUtils.isNotEmpty(musicIds)) {

                freeNum = musicSheetMapper.selectBatchIds(musicIds).stream()
                        .filter(x -> ChargeTypeEnum.FREE.match(x.getPaymentType()))
                        .count();
            }

            // 已添加曲目统计
            Map<Long, Integer> collect = getBaseMapper().selectAlbumMusicSheetStatInfo(albumId, ChargeTypeEnum.FREE).stream()
                    .collect(Collectors.toMap(StatGroupWrapper::getId, StatGroupWrapper::getTotal, (o, n) -> n));

            if ((collect.getOrDefault(albumId, 0) + freeNum) > 2) {
                throw new BizException("专辑免费曲目最多2首");
            }
        }*/

        return albumMusicRelateService.addMusicSheet(albumId,albumMusicList,userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createMusicAlbum(MusicAlbum musicAlbum) {
        if (checkNameRepeat(musicAlbum.getAlbumName(),musicAlbum.getId())) {
            throw new BizException("专辑名称重复");
        }
        if (musicAlbum.getAuditVersion() == null) {
            musicAlbum.setAuditVersion(YesOrNoEnum.NO);
        }
        musicAlbum.setDelFlag(false);
        return this.save(musicAlbum);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMusicAlbum(MusicAlbum musicAlbum) {
        if (checkNameRepeat(musicAlbum.getAlbumName(),musicAlbum.getId())) {
            throw new BizException("专辑名称重复");
        }
        if (musicAlbum.getAuditVersion() == null) {
            musicAlbum.setAuditVersion(YesOrNoEnum.NO);
        }

        // 非付费类型，已添加曲目或者已购买，不允许修改付费方式
        /*MusicAlbum album = getById(musicAlbum.getId());
        if (Objects.isNull(album)) {
            throw new BizException("无效的专辑ID");
        }*/

        // 专辑从免费修改为付费方式，需要判断当前免费单曲数量
        /*if (Objects.nonNull(musicAlbum.getPaymentType())
                && ChargeTypeEnum.FREE.match(album.getPaymentType())
                && !album.getPaymentType().equals(musicAlbum.getPaymentType())) {

            Map<Long, Integer> collect = getBaseMapper().selectAlbumMusicSheetStatInfo(album.getId(), ChargeTypeEnum.FREE).stream()
                    .collect(Collectors.toMap(StatGroupWrapper::getId, StatGroupWrapper::getTotal, (o, n) -> n));

            if (collect.getOrDefault(album.getId(), 0) > 2) {
                throw new BizException(MessageFormat.format("当前专辑免费单曲数为 {0}, 已超过免费数量", collect.get(album.getId())));
            }
        }*/

        return this.updateById(musicAlbum);
    }

    @Override
    public YesOrNoEnum checkFavorite(Long studentId, Long albumId, ClientEnum clientType) {
        List<AlbumFavorite> albumFavorites = albumFavoriteService.getFavorite(studentId,albumId, clientType);

        return CollectionUtils.isEmpty(albumFavorites)?YesOrNoEnum.NO:YesOrNoEnum.YES;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean setFavorite(Long studentId, Long albumId, ClientEnum clientType) {
        List<AlbumFavorite> albumFavorites = albumFavoriteService.getFavorite(studentId,albumId, clientType);
        if (CollectionUtils.isEmpty(albumFavorites)) {
            AlbumFavorite albumFavorite = new AlbumFavorite();
            albumFavorite.setAlbumId(albumId);
            albumFavorite.setClientType(clientType);
            albumFavorite.setUserId(studentId);
            albumFavorite.setFavoriteTime(new Date());
            return albumFavoriteService.save(albumFavorite);
        } else {
            List<Long> ids = albumFavorites.stream().map(AlbumFavorite::getId).collect(Collectors.toList());
            return albumFavoriteService.removeByIds(ids);
        }
    }

    @Override
    public IPage<MusicAlbumVo> favoriteAlbum(IPage<MusicAlbumVo> page, StudentMusicAlbumSearch search, ClientEnum clientType) {

        IPage<MusicAlbumVo> iPage = page.setRecords(baseMapper.selectFavoritePage(page, search, clientType));
        List<MusicAlbumVo> records = iPage.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return iPage;
        }
        List<MusicAlbumVo> favoriteNumAndMusicNumList =baseMapper.selectFavoriteNumAndMusicNum(records);

        for (int i = 0; i < records.size(); i++) {
            records.get(i).setAlbumFavoriteCount(favoriteNumAndMusicNumList.get(i).getAlbumFavoriteCount());
            records.get(i).setMusicSheetCount(favoriteNumAndMusicNumList.get(i).getMusicSheetCount());
        }
        return iPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean del(Long id) {
        MusicAlbum musicAlbum = new MusicAlbum();
        musicAlbum.setDelFlag(true);
        musicAlbum.setId(id);
        return this.updateById(musicAlbum);
    }

    @Override
    public IPage<MusicAlbumVo> selectStudentPage(IPage<MusicAlbumVo> page, MusicAlbumSearch query, ClientEnum clientType) {
    	List<MusicAlbumVo> records = baseMapper.selectStudentPage(page, query, clientType);
    	/*if(records == null || records.size() == 0){
    		query.setSubjectIdList(null);
    		records = baseMapper.selectStudentPage(page, query);
    	}*/
        IPage<MusicAlbumVo> iPage = page.setRecords(records);

        List<Long> albumIds = records.stream().map(MusicAlbumVo::getId).collect(Collectors.toList());
        if (query.getUserId() == null || CollectionUtils.isEmpty(albumIds)) {
            return iPage;
        }
        albumIds = albumFavoriteService.selectFavorite(query.getUserId(), albumIds, clientType);
        for (MusicAlbumVo record : records) {
            if(albumIds.contains(record.getId())) {
                record.setFavorite(YesOrNoEnum.YES);
            } else {
                record.setFavorite(YesOrNoEnum.NO);
            }
        }
        return iPage;
    }

    @Override
    public Boolean updateMusicSheet(MusicAlbumSheetSortDto query) {

         return albumMusicRelateService.lambdaUpdate()
                .eq(AlbumMusicRelate::getAlbumId,query.getAlbumId())
                .eq(AlbumMusicRelate::getMusicSheetId,query.getMusicSheetId())
                .set(AlbumMusicRelate::getSortNumber,query.getSortNumber())
                .update();


    }

    @Override
    public ShareProfitVo albumShareProfit(SysUser sysUser, Long albumId) {
        MusicAlbumDetailSearch query = new MusicAlbumDetailSearch();

        query.setId(albumId);
        query.setType(2);
        query.setRows(200);
        query.setState(YesOrNoEnum.YES);
        AlbumDetailVo detail = detail(PageUtil.getPage(query), query, null, null);
        if (detail == null) {
            throw new BizException("未找到专辑信息");
        }
        ShareProfitVo shareProfitVo = new ShareProfitVo();
        ActivityPlanVo activityPlanVo = activityPlanService.activityShare(ActivityShareEnum.VIP, sysUser.getId());
        if (activityPlanVo != null) {
            shareProfitVo.setActivityId(activityPlanVo.getId());
            shareProfitVo.setDiscount(YesOrNoEnum.YES);
        }
        shareProfitVo.setTeacherId(sysUser.getId());
        shareProfitVo.setName(sysUser.getUsername());
        shareProfitVo.setAvatar(sysUser.getAvatar());
        shareProfitVo.setType("ALBUM");
        shareProfitVo.setMusicAlbum(detail);
        return shareProfitVo;
    }

    private boolean checkNameRepeat(String albumName, Long id) {
        LambdaQueryChainWrapper<MusicAlbum> eq = this.lambdaQuery()
                                                     .eq(MusicAlbum::getDelFlag,0)
                                                   .eq(MusicAlbum::getAlbumName, albumName);
        if (id != null) {
            eq.ne(MusicAlbum::getId,id);
        }
        return eq.count() != 0;
    }
}