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.yonge.cooleshow.auth.api.client.SysUserFeignService;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.common.enums.PostStatusEnum;
import com.yonge.cooleshow.biz.dal.dao.MusicSheetDao;
import com.yonge.cooleshow.biz.dal.dto.MusicSheetDto;
import com.yonge.cooleshow.biz.dal.dto.MusicSheetExport;
import com.yonge.cooleshow.biz.dal.dto.MusicSheetPayDto;
import com.yonge.cooleshow.biz.dal.dto.UserAccountRecordDto;
import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
import com.yonge.cooleshow.biz.dal.dto.req.TeacherMusicSheetAuditReq;
import com.yonge.cooleshow.biz.dal.dto.search.*;
import com.yonge.cooleshow.biz.dal.entity.*;
import com.yonge.cooleshow.biz.dal.enums.*;
import com.yonge.cooleshow.biz.dal.service.*;
import com.yonge.cooleshow.common.enums.YesOrNoEnum;
import com.yonge.toolset.mybatis.support.PageUtil;
import com.yonge.cooleshow.biz.dal.vo.*;
import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
import com.yonge.cooleshow.common.constant.SysConfigConstant;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.base.string.MessageFormatter;
import com.yonge.toolset.base.util.StringUtil;
import com.yonge.toolset.thirdparty.message.MessageSenderPluginContext;
import com.yonge.toolset.utils.easyexcel.ErrMsg;
import com.yonge.toolset.utils.easyexcel.ExcelDataReaderProperty;
import com.yonge.toolset.utils.easyexcel.ExcelException;
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 org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

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

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

    @Autowired
    private MusicSheetDao musicSheetDao;

    @Autowired
    private MusicSheetAccompanimentService musicSheetAccompanimentService;

    @Autowired
    private MusicFavoriteService musicFavoriteService;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private MusicSheetPurchaseRecordService musicSheetPurchaseRecordService;

    @Autowired
    private MusicSheetPracticeRecordService musicSheetPracticeRecordService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private MusicSheetAuthRecordService musicSheetAuthRecordService;

    @Autowired
    private AlbumMusicRelateService albumMusicRelateService;

    @Autowired
    private SysUserFeignService sysUserFeignService;

    @Autowired
    private SysMessageService sysMessageService;

    @Autowired
    private UserAccountService userAccountService;

    @Autowired
    private MusicTagService musicTagService;

    @Autowired
    private SubjectService subjectService;

    @Autowired
    private TeacherService teacherService;

    @Autowired
    private StudentStarService studentStarService;

    public MusicSheetDao getDao() {
        return musicSheetDao;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean saveMp3AndAccompaniment(MusicSheetDto musicSheetDto, Long userId) {
        MusicSheet musicSheet = new MusicSheet();
        BeanUtils.copyProperties(musicSheetDto, musicSheet);
        //保存主表
        musicSheet.setUpdateBy(userId);
        musicSheet.setUpdateTime(new Date());
        musicSheet.setState(YesOrNoEnum.NO);
        this.saveOrUpdate(musicSheet);

        if (musicSheet.getAuditStatus() == null || AuthStatusEnum.DOING.getCode().equals(musicSheet.getAuditStatus().getCode())) {
            musicSheetAuthRecordService.setAuditDoing(musicSheet.getId());
        }

        Long sheetId = musicSheet.getId();
        List<MusicSheetAccompaniment> list = musicSheetDto.getBackground();
        list.forEach(musicSheetAccompaniment -> musicSheetAccompaniment.setMusicSheetId(sheetId).setCreateBy(userId).setCreateTime(new Date()));
        return musicSheetAccompanimentService.saveBatch(list);

    }

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean state(Long id) {
        MusicSheet musicSheet = this.getById(id);
        if (musicSheet == null) {
            throw new BizException("未找到曲目信息");
        }
        if (YesOrNoEnum.NO.getCode().equals(musicSheet.getState().getCode())) {
            musicSheet.setState(YesOrNoEnum.YES);
        } else {
            musicSheet.setState(YesOrNoEnum.NO);
        }
        return this.updateById(musicSheet);

    }

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

    @Override
    public MusicSheetShareVo shareMusicSheet(SysUser sysUser) {
        MusicSheetSearch query = new MusicSheetSearch();
        // 设置只查老师用户
        query.setCreateBy(sysUser.getId());
        query.setAuditStatus(AuthStatusEnum.PASS);
        query.setState(YesOrNoEnum.YES);
        query.setDelFlag(false);
        query.setSourceType(SourceTypeEnum.TEACHER);
        // 只查3条
        query.setRows(3);
        IPage<MusicSheetVo> musicSheetVoIPage = selectPage(PageUtil.getPage(query), query);
        MusicSheetShareVo musicSheetShareVo = new MusicSheetShareVo();
        musicSheetShareVo.setMusicSheetCount(musicSheetVoIPage.getTotal());
        musicSheetShareVo.setMusicSheetVoList(musicSheetVoIPage.getRecords());
        musicSheetShareVo.setName(sysUser.getUsername());
        musicSheetShareVo.setAvatar(sysUser.getAvatar());

        String teacherMusicShareUrl = sysConfigService.findConfigValue(SysConfigConstant.TEACHER_MUSIC_SHEET_SHARE_URL);
        musicSheetShareVo.setUrl(MessageFormatter.arrayFormat(teacherMusicShareUrl, sysUser.getId()));

        return musicSheetShareVo;
    }

    @Override
    public MusicSheetDetailVo detail(Long id, SysUser sysUser,ClientEnum userType) {
        MusicSheetDetailVo detail = baseMapper.detail(id);
        if (detail == null) {
            throw new BizException("未找到曲目信息");
        }
        if (sysUser == null) {
            return detail;
        }
        if (AuthStatusEnum.UNPASS.getCode().equals(detail.getAuditStatus().getCode())) {
            String reason = musicSheetAuthRecordService.selectAuditReason(id);
            detail.setReason(reason);
        }
        if (ChargeTypeEnum.FREE.getCode().equals(detail.getChargeType().getCode())) {
            detail.setPlay(YesOrNoEnum.YES);
        }  else if (ClientEnum.STUDENT.getCode().equals(userType.getCode())
                || ClientEnum.TEACHER.getCode().equals(userType.getCode())) {
            // 2022 7 20  老师也能购买曲目
            if (ClientEnum.TEACHER.getCode().equals(userType.getCode()) && detail.getUserId().equals(sysUser.getId())) {
                detail.setPlay(YesOrNoEnum.YES);
            } else {
                setMusicSheetPlay(sysUser.getId(), detail,userType);
            }
        } else {
            detail.setPlay(YesOrNoEnum.YES);
        }
        if (ClientEnum.STUDENT.getCode().equals(userType.getCode())) {
            // 学生进入小酷Ai练习，添加一条练习记录
            musicSheetPracticeRecordService.addRecord(id, sysUser.getId());
        }
        return detail;
    }

    /**
     * 设置学生曲目信息
     *
     * 2022 7 20  老师也能购买曲目
     *  @param studentId 学生id
     * @param detail 曲目详情
     * @param userType 用户类型
     */
    private void setMusicSheetPlay(Long studentId, MusicSheetDetailVo detail, ClientEnum userType) {
        detail.setPlay(YesOrNoEnum.NO);
        // 单曲购买 判断购买记录，有记录课播放
        if (ChargeTypeEnum.CHARGE.getCode().equals(detail.getChargeType().getCode())) {
            // 学生须判断是否能播放曲目
            MusicSheetPurchaseRecord musicSheetPurchaseRecord = musicSheetPurchaseRecordService.checkPurchase(
                    studentId, detail.getId(),userType);
            if (musicSheetPurchaseRecord != null) {
                detail.setOrderStatus(musicSheetPurchaseRecord.getOrderStatus());
                detail.setOrderNo(musicSheetPurchaseRecord.getOrderNo());
                if (OrderStatusEnum.PAID.getCode().equals(musicSheetPurchaseRecord.getOrderStatus().getCode())) {
                    detail.setPlay(YesOrNoEnum.YES);
                }
            }
        } else if (ChargeTypeEnum.VIP.getCode().equals(detail.getChargeType().getCode())) {
            // 会员 判断是否为会员， 会员可播放
            if (userType.equals(ClientEnum.STUDENT)) {
                StudentVo studentVo = studentService.detail(studentId);
                if (studentVo != null && YesOrNoEnum.YES.getCode().equals(studentVo.getIsVip().getCode())) {
                    detail.setPlay(YesOrNoEnum.YES);
                }
            } else if (userType.equals(ClientEnum.TEACHER)) {
                TeacherVo teacher= teacherService.detail(studentId);
                if (teacher != null && YesOrNoEnum.YES.getCode().equals(teacher.getIsVip().getCode())) {
                    detail.setPlay(YesOrNoEnum.YES);
                }
            }
        }
    }

    @Override
    public IPage<MusicSheetVo> selectStudentPage(IPage<MusicSheetVo> page, StudentMusicSheetSearch query) {
        IPage<MusicSheetVo> musicSheetVoIPage = page.setRecords(baseMapper.selectStudentMusicPage(page, query));
        List<MusicSheetVo> records = musicSheetVoIPage.getRecords();
        if (query.getStudentId() != null) {
            StudentVo studentVo = studentService.detail(query.getStudentId());
            if (studentVo == null) {
                return musicSheetVoIPage;
            }
            for (MusicSheetVo record : records) {
                if (ChargeTypeEnum.VIP.getCode().equals(record.getChargeType().getCode())
                        && YesOrNoEnum.YES.getCode().equals(studentVo.getIsVip().getCode())) {
                    record.setPlay(YesOrNoEnum.YES);
                }
            }
        }
        return musicSheetVoIPage;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean setFavorite(Long userId, Long musicSheetId) {
        List<MusicFavorite> musicFavorites = musicFavoriteService.getFavorite(userId, musicSheetId);
        if (CollectionUtils.isEmpty(musicFavorites)) {
            MusicFavorite musicFavorite = new MusicFavorite();
            musicFavorite.setMusicSheetId(musicSheetId);
            musicFavorite.setUserId(userId);
            musicFavorite.setFavoriteTime(new Date());
            return musicFavoriteService.save(musicFavorite);
        } else {
            List<Long> ids = musicFavorites.stream().map(MusicFavorite::getId).collect(Collectors.toList());
            return musicFavoriteService.removeByIds(ids);
        }
    }

    @Override
    public IPage<MusicSheetVo> myMusic(IPage<MusicSheetVo> page, StudentMusicSheetSearch query) {
        return page.setRecords(baseMapper.selectMyMusicPage(page, query));
    }

    @Override
    public IPage<MusicSheetVo> favoriteMusic(IPage<MusicSheetVo> page, StudentMusicSheetSearch query) {
        return page.setRecords(baseMapper.selectFavoriteMusicPage(page, query));
    }

    @Override
    public IPage<MusicSheetVo> practiceMusic(IPage<MusicSheetVo> page, StudentMusicSheetSearch query) {
        // 预计最近练习表数据量会很多
        // 先找到最近练习的曲目id 在根据曲目id进行精确查找
        IPage<Long> practiceMusicIdPage = musicSheetPracticeRecordService.selectPracticeMusic(query, page.getPages(), page.getSize());
        List<Long> practiceMusicIdList = practiceMusicIdPage.getRecords();
        if (CollectionUtils.isEmpty(practiceMusicIdList)) {
            page.setRecords(new ArrayList<>());
            return page;
        }
        // 构建分页信息
        page.setRecords(baseMapper.selectPracticeMusicPage(query, practiceMusicIdList));
        page.setPages(practiceMusicIdPage.getPages());
        page.setCurrent(practiceMusicIdPage.getCurrent());
        page.setSize(practiceMusicIdPage.getSize());
        page.setTotal(practiceMusicIdPage.getTotal());
        return page;
    }

    @Override
    public IPage<StudentMusicSheetOrderVo> selectStudentOrderPage(IPage<StudentMusicSheetOrderVo> page, StudentMusicSheetOrderSearch query) {
        return page.setRecords(baseMapper.selectStudentOrderPage(page, query));
    }

    @Override
    public IPage<TeacherMusicSheetVo> selectTeacherPage(IPage<TeacherMusicSheetVo> page, TeacherMusicSheetSearch query) {
        return page.setRecords(baseMapper.selectTeacherPage(page, query));
    }

    @Override
    public IPage<TeacherMusicSheetVo> selectAuditPage(IPage<TeacherMusicSheetVo> page, TeacherMusicSheetAuditSearch query) {
        return page.setRecords(baseMapper.selectAuditPage(page, query));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean audit(TeacherMusicSheetAuditReq param, Long userId) {

        MusicSheet musicSheet = this.getById(param.getMusicSheetId());
        if (musicSheet == null) {
            throw new BizException("未找到曲目信息");
        }
        if (!AuthStatusEnum.DOING.getCode().equals(musicSheet.getAuditStatus().getCode())) {
            throw new BizException("曲目已经过审批");
        }

        boolean flag = false;
        if (musicSheetAuthRecordService.audit(param, userId)) {
            musicSheet.setAuditStatus(param.getAuthStatus());
            musicSheet.setUpdateBy(userId);
            musicSheet.setUpdateTime(new Date());
            if (AuthStatusEnum.PASS.getCode().equals(param.getAuthStatus().getCode())) {
                musicSheet.setState(YesOrNoEnum.YES);

                // 修改老师标签
                teacherService.setTeacherTag(musicSheet.getUserId(), TeacherTagEnum.MUSIC);

            }
            flag = this.updateById(musicSheet);
        }

        // 发送审核通知
        Map<Long, String> receivers = new HashMap<>();
        SysUser teacher = sysUserFeignService.queryUserById(musicSheet.getUserId());
        receivers.put(musicSheet.getUserId(), teacher.getPhone());
        try {
            sendMusicSheetAuditMessage(param, musicSheet, receivers);
        } catch (Exception e) {
            log.warn("曲目审核消息发送失败，{}", e.getMessage());
        }

        return flag;
    }

    // 发送曲目审核消息
    private void sendMusicSheetAuditMessage(TeacherMusicSheetAuditReq param, MusicSheet musicSheet, Map<Long, String> receivers) {
        if (AuthStatusEnum.PASS.getCode().equals(param.getAuthStatus().getCode())) {
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.MUSIC_SHEET_AUTH_PASS,
                    receivers, null, 0, null, ClientEnum.TEACHER.getCode(), musicSheet.getMusicSheetName());
        } else if (AuthStatusEnum.UNPASS.getCode().equals(param.getAuthStatus().getCode())) {
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.MUSIC_SHEET_AUTH_UNPASS,
                    receivers, null, 0, null, ClientEnum.TEACHER.getCode(), musicSheet.getMusicSheetName(),
                    param.getRemark());
        }
    }

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

        MusicSheet musicSheet = super.getById(id);
        if (YesOrNoEnum.YES.getCode().equals(musicSheet.getState().getCode())) {
            throw new BizException("启用状态下，不可删除");
        }
        musicSheet.setDelFlag(true);
        return this.updateById(musicSheet);
    }

    @Override
    public Integer countTeacherMusicSheet(SysUser sysUser) {
        return this.lambdaQuery()
                .eq(MusicSheet::getAuditStatus, AuthStatusEnum.PASS)
                .eq(MusicSheet::getCreateBy, sysUser.getId())
                .eq(MusicSheet::getState, YesOrNoEnum.YES)
                .eq(MusicSheet::getDelFlag, YesOrNoEnum.NO)
                .eq(MusicSheet::getSourceType, SourceTypeEnum.TEACHER.getCode())
                .count();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveMusicSheet(MusicSheetDto musicSheetDto, Long userId) {

        if (musicSheetDto.getId() != null) {
            musicSheetAccompanimentService.delByMusicSheetId(musicSheetDto.getId());
        }

        if (musicSheetDto.getAuditVersion() == null) {
            musicSheetDto.setAuditVersion(YesOrNoEnum.NO);
        }

        // 删除曲目专辑关联
        delAlbumSheetRef(musicSheetDto.getId(), musicSheetDto.getMusicSubject());

        List<MusicSheetAccompaniment> list;
        if (!AudioTypeEnum.MIDI.getCode().equals(musicSheetDto.getAudioType().getCode())) {
            list = musicSheetDto.getBackground();
            if (CollectionUtils.isEmpty(list)) {
                throw new BizException("mp3音频文件对应的主音或者伴奏文件没有提供");
            }
            return saveMp3AndAccompaniment(musicSheetDto, userId);
        } else {
            MusicSheet musicSheet = new MusicSheet();
            BeanUtils.copyProperties(musicSheetDto, musicSheet);
            musicSheet.setUpdateTime(new Date());
            musicSheet.setUpdateBy(userId);
            musicSheet.setState(YesOrNoEnum.NO);
            this.saveOrUpdate(musicSheet);
            if (musicSheet.getAuditStatus() == null || AuthStatusEnum.DOING.getCode().equals(musicSheet.getAuditStatus().getCode())) {
                musicSheetAuthRecordService.setAuditDoing(musicSheet.getId());
            }

            return true;
        }
    }

    /**
     * 删除专辑曲目关联
     *
     * @param id        曲目id
     * @param subjectId 声部id
     */
    private void delAlbumSheetRef(Long id, String subjectId) {

        if (id == null) {
            return;
        }
        MusicSheet musicSheet = this.getById(id);
        if (musicSheet.getMusicSubject().equals(subjectId)) {
            return;
        }
        albumMusicRelateService.delByMusicSheet(musicSheet.getId());


    }

    @Override
    public HttpResponseResult<OrderCreateRes> buyMusicSheetCheck(OrderReq.OrderReqInfo orderReqInfo) {

        // 下单前的验证
        getSysUser(orderReqInfo.getUserId());

        MusicSheetPayDto musicSheetPayDto = JSON.parseObject(
                JSON.toJSONString(orderReqInfo.getBizContent()), MusicSheetPayDto.class);

        MusicSheet musicSheet = this.getById(musicSheetPayDto.getMusicSheetId());
        OrderCreateRes orderCreateRes = new OrderCreateRes();
        if (musicSheet == null) {
            throw new BizException("不存在曲目信息");
        }

        // 检查已经购买
        checkoutPay(orderReqInfo.getUserId(), musicSheetPayDto.getMusicSheetId(),musicSheetPayDto.getClientType());

        orderCreateRes.setRes(true);
        if (!musicSheet.getSourceType().getCode().equals(SourceTypeEnum.PLATFORM.getCode())) {
            orderCreateRes.setMerchId(musicSheet.getUserId());
        }
        orderCreateRes.setGoodType(orderCreateRes.getGoodType());
        orderCreateRes.setBizId(musicSheet.getId());
        orderCreateRes.setGoodNum(1);
        orderCreateRes.setOriginalPrice(musicSheet.getMusicPrice());
        orderCreateRes.setExpectPrice(musicSheet.getMusicPrice());
        return HttpResponseResult.succeed(orderCreateRes);

    }

    /**
     * 检查是否已购买当前曲目
     *  @param userId       用户id
     * @param musicSheetId 曲目id
     * @param clientType
     */
    private void checkoutPay(Long userId, Long musicSheetId, String clientType) {
        List<MusicSheetPurchaseRecord> list = musicSheetPurchaseRecordService
                .lambdaQuery()
                .eq(MusicSheetPurchaseRecord::getMusicSheetId, musicSheetId)
                .eq(MusicSheetPurchaseRecord::getStudentId, userId)
                .eq(MusicSheetPurchaseRecord::getClientType, clientType)
                .eq(MusicSheetPurchaseRecord::getOrderStatus, OrderStatusEnum.PAID)
                .list();
        if (!CollectionUtils.isEmpty(list)) {
            throw new BizException("已经购买了当前曲目");
        }
    }

    @Override
    @Transactional
    public void buyMusicSheetSuccess(UserOrderDetailVo userOrderDetailVo) {
        MusicSheet musicSheet = this.getById(userOrderDetailVo.getBizId());
        // 曲目服务费比例
        String musicSheetServiceFee = sysConfigService.findConfigValue(SysConfigConstant.MUSIC_SHEET_SERVICE_FEE);
        BigDecimal serviceFee = new BigDecimal(musicSheetServiceFee).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
        //支付金额
        BigDecimal actualPrice = userOrderDetailVo.getActualPrice();

        //服务费
        BigDecimal serviceFeeAmount = actualPrice.multiply(serviceFee).setScale(2, RoundingMode.HALF_UP);

        // 保存购买记录
        addMusicSheetPurchaseRecord(userOrderDetailVo, actualPrice, serviceFeeAmount);

        if (!musicSheet.getSourceType().getCode().equals(SourceTypeEnum.PLATFORM.getCode())) {
            // 加入账户
            addTeacherAccount(userOrderDetailVo, actualPrice, serviceFeeAmount, userOrderDetailVo.getBizId());
        }

        // 消息通知
        try {
            sendBuyMessage(userOrderDetailVo.getMerchId(), userOrderDetailVo.getUserId(), userOrderDetailVo.getBizId());
        } catch (Exception e) {
            log.warn("学生购买曲目消息推送失败 {}", e.getMessage());
        }
    }

    /**
     * 发送购买消息通知
     *
     * @param teacherId    老师id
     * @param studentId    学生id
     * @param musicSheetId 曲目id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean sendBuyMessage(Long teacherId, Long studentId, Long musicSheetId) {
        SysUser teacher = sysUserFeignService.queryUserById(teacherId);
        SysUser student = sysUserFeignService.queryUserById(studentId);
        if (StringUtil.isEmpty(teacher.getPhone())) {
            log.warn("teacher id {} name {} 手机号不存在，消息推送失败", teacher.getId(), teacher.getUsername());
        }

        MusicSheet musicSheet = this.getById(musicSheetId);
        // 推送老师
        Map<Long, String> teacherReceivers = new HashMap<>();
        teacherReceivers.put(teacherId, teacher.getPhone());

        sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG,
                MessageTypeEnum.STUDENT_BUY_TEACHER_MUSIC_SHEET, teacherReceivers, null,
                0, null, ClientEnum.TEACHER.getCode(), student.getUsername(), musicSheet.getMusicSheetName());

        // 推送学生
        Map<Long, String> studentReceivers = new HashMap<>();
        studentReceivers.put(studentId, student.getPhone());


        String url = sysMessageService.selectConfigUrl(MessageTypeEnum.STUDENT_BUY_MUSIC_SHEET_SUCCESS.getCode());

        sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG,
                MessageTypeEnum.STUDENT_BUY_MUSIC_SHEET_SUCCESS, studentReceivers, null,
                0, url, ClientEnum.STUDENT.getCode(), musicSheet.getMusicSheetName());
        // 推送学生
        Map<Long, String> studentSMS = new HashMap<>();
        studentSMS.put(studentId, student.getPhone());
        // 推送短信
        url = sysMessageService.selectConfigUrl(MessageTypeEnum.SMS_STUDENT_BUY_MUSIC_SHEET_SUCCESS.getCode());
        sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.SMS_STUDENT_BUY_MUSIC_SHEET_SUCCESS,
                studentSMS, null, 0, url, null, musicSheet.getMusicSheetName());

        return true;
    }

    /**
     * 保存购买记录
     *
     * @param userOrderDetailVo 订单信息
     * @param actualPrice       付款价格
     * @param serviceFeeAmount  服务费
     */
    private void addMusicSheetPurchaseRecord(UserOrderDetailVo userOrderDetailVo, BigDecimal actualPrice, BigDecimal serviceFeeAmount) {
        MusicSheetPurchaseRecord musicSheetPurchaseRecord = musicSheetPurchaseRecordService
                .checkPurchase(userOrderDetailVo.getUserId(), userOrderDetailVo.getBizId(),userOrderDetailVo.getOrderClient());
        if (musicSheetPurchaseRecord == null) {
            musicSheetPurchaseRecord = new MusicSheetPurchaseRecord();
        }
        musicSheetPurchaseRecord.setClientType(userOrderDetailVo.getOrderClient());
        musicSheetPurchaseRecord.setMusicSheetId(userOrderDetailVo.getBizId());
        musicSheetPurchaseRecord.setOrderNo(userOrderDetailVo.getOrderNo());
        musicSheetPurchaseRecord.setPurchasePrice(actualPrice);
        musicSheetPurchaseRecord.setPurchaseTime(new Date());
        musicSheetPurchaseRecord.setTeacherId(userOrderDetailVo.getMerchId());
        musicSheetPurchaseRecord.setOriginalPrice(userOrderDetailVo.getOriginalPrice());
        musicSheetPurchaseRecord.setMusicSheetServiceFee(serviceFeeAmount);
        musicSheetPurchaseRecord.setOrderStatus(OrderStatusEnum.PAID);
        musicSheetPurchaseRecord.setStudentId(userOrderDetailVo.getUserId());
        musicSheetPurchaseRecordService.saveOrUpdate(musicSheetPurchaseRecord);
    }

    /**
     * 添加金额到老师账户
     *
     * @param userOrderDetailVo 订单信息
     * @param actualPrice       付款价格
     * @param serviceFeeAmount  服务费
     * @param musicSheetId      曲目id
     */
    private void addTeacherAccount(UserOrderDetailVo userOrderDetailVo, BigDecimal actualPrice, BigDecimal serviceFeeAmount,
                                   Long musicSheetId) {
        BigDecimal transAmount = actualPrice.subtract(serviceFeeAmount).setScale(2, RoundingMode.HALF_UP);
        //插入老师账户变更记录-老师预收
        userAccountService.accountRecord(
                new UserAccountRecordDto(userOrderDetailVo.getMerchId(), PostStatusEnum.WAIT, transAmount, InOrOutEnum.IN,
                        AccountBizTypeEnum.MUSIC, musicSheetId, userOrderDetailVo.getGoodName(), userOrderDetailVo.getOrderNo(),userOrderDetailVo.getUserId()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderAfterSheet(UserOrderDetailVo userOrderDetailVo) {
        // 保存购买记录
        MusicSheetPurchaseRecord musicSheetPurchaseRecord = musicSheetPurchaseRecordService
                .checkPurchase(userOrderDetailVo.getUserId(),userOrderDetailVo.getBizId(),userOrderDetailVo.getOrderClient());
        if (musicSheetPurchaseRecord == null) {
            musicSheetPurchaseRecord = new MusicSheetPurchaseRecord();
        }
        musicSheetPurchaseRecord.setMusicSheetId(userOrderDetailVo.getBizId());
        musicSheetPurchaseRecord.setOrderNo(userOrderDetailVo.getOrderNo());
        musicSheetPurchaseRecord.setTeacherId(userOrderDetailVo.getMerchId());
        musicSheetPurchaseRecord.setOriginalPrice(userOrderDetailVo.getOriginalPrice());
        musicSheetPurchaseRecord.setOrderStatus(OrderStatusEnum.WAIT_PAY);
        musicSheetPurchaseRecord.setStudentId(userOrderDetailVo.getUserId());
        musicSheetPurchaseRecordService.saveOrUpdate(musicSheetPurchaseRecord);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void buyMusicSheetCancel(UserOrderDetailVo userOrderDetailVo) {
        MusicSheetPurchaseRecord musicSheetPurchaseRecord = musicSheetPurchaseRecordService
                .checkPurchase(userOrderDetailVo.getUserId(),userOrderDetailVo.getBizId(),userOrderDetailVo.getOrderClient());

        if (musicSheetPurchaseRecord == null) return;
        musicSheetPurchaseRecordService.removeById(musicSheetPurchaseRecord.getId());
    }

    @Override
    public Integer getTeacherMusicSheetCount(Long userId) {
        return baseMapper.selectTeacherMusicSheetCount(userId);

    }

    @Override
    public HomeMusicSheetVo getMusicSheetHome() {

        HomeMusicSheetVo homeMusicSheetVo = baseMapper.selectMusicNum();
        homeMusicSheetVo.setMusicSheetSmallList(baseMapper.selectPayMusicSheet());

        return homeMusicSheetVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importExcel(List<ExcelDataReaderProperty<MusicSheetExport>> dataList, Long userId) {

        List<ErrMsg> errMsgList = new ArrayList<>();
        dataList.sort(Comparator.comparingInt(ExcelDataReaderProperty::getRowIndex));
        List<MusicSheetDto> musicSheetDtoList = new ArrayList<>();
        List<MusicTagVo> musicTagVoList = musicTagService.selectMusicTagTree();
        List<Subject> subjects = subjectService.subjectSelect();
        Date date = new Date();
        for (ExcelDataReaderProperty<MusicSheetExport> readerProperty : dataList) {
            MusicSheetDto musicSheetDto = new MusicSheetDto();
            musicSheetDto.setUserId(userId);
            musicSheetDto.setAuditVersion(YesOrNoEnum.NO);
            musicSheetDto.setSourceType(SourceTypeEnum.PLATFORM);
            musicSheetDto.setChargeType(ChargeTypeEnum.FREE);
            musicSheetDto.setAuditStatus(AuthStatusEnum.PASS);
            musicSheetDto.setState(YesOrNoEnum.NO);
            musicSheetDto.setDelFlag(false);
            musicSheetDto.setCreateBy(userId);
            musicSheetDto.setUpdateBy(userId);
            musicSheetDto.setCreateTime(date);
            musicSheetDto.setUpdateTime(date);

            String errMsg = readerProperty.getErrorMessage();
            if (!StringUtil.isEmpty(errMsg)) {
                errMsgList.add(new ErrMsg(readerProperty.getRowIndex(), errMsg));
                continue;
            }
            MusicSheetExport sheetExport = readerProperty.getClazz();
            BeanUtils.copyProperties(sheetExport, musicSheetDto);

            if (AudioTypeEnum.MIDI.getCode().equals(musicSheetDto.getAudioType().getCode())) {
                musicSheetDto.setMp3Type(null);
            }

            if (musicSheetDto.getAudioType().equals(AudioTypeEnum.MP3)) {
                musicSheetDto.setUrl(musicSheetDto.getMidiUrl());
                musicSheetDto.setMidiUrl("");
            }

            String musicTags = sheetExport.getMusicTags();
            StringBuilder musicTagIds = new StringBuilder();
            if (musicTags == null || musicTags.equals("")) {
                errMsgList.add(new ErrMsg(readerProperty.getRowIndex(), "曲目标签不能为空"));
            } else {
                String[] stringList = musicTags.split("[,，]");
                List<MusicTag> childrenMusicTag = new ArrayList<>();
                for (MusicTagVo musicTagVo : musicTagVoList) {
                    childrenMusicTag.addAll(musicTagVo.getChildren());
                }
                for (String s : stringList) {
                    boolean b = false;
                    for (MusicTag musicTag : childrenMusicTag) {
                        if (musicTag.getName().equals(s)) {
                            if (musicTagIds.length() != 0) {
                                musicTagIds.append(",");
                            }
                            musicTagIds.append(musicTag.getId());
                            b = true;
                        }
                    }
                    if (!b) {
                        errMsgList.add(new ErrMsg(readerProperty.getRowIndex(), "曲目名称错误：" + s));
                    }
                }
            }
            if (StringUtil.isEmpty(sheetExport.getComposer())) {
                errMsgList.add(new ErrMsg(readerProperty.getRowIndex(), "音乐人不能为空"));
            }
            if (StringUtil.isEmpty(sheetExport.getMusicSubjects())) {
                errMsgList.add(new ErrMsg(readerProperty.getRowIndex(), "曲目声部不能为空"));
            } else {
                List<Subject> childrenSubject = new ArrayList<>();
                for (Subject subject : subjects) {
                    if (CollectionUtils.isEmpty(subject.getSubjects())) {
                        continue;
                    }
                    childrenSubject.addAll(subject.getSubjects());
                }
                List<Subject> collect = childrenSubject.stream()
                        .filter(subject -> subject.getName().equals(sheetExport.getMusicSubjects()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(collect)) {
                    errMsgList.add(new ErrMsg(readerProperty.getRowIndex(), "曲目声部名错误：" + sheetExport.getMusicSubjects()));
                } else {
                    musicSheetDto.setMusicSubject(collect.get(0).getId().toString());
                }
            }
            if (!StringUtil.isEmpty(sheetExport.getAudioFileUrls())) {

                List<MusicSheetAccompaniment> background = new ArrayList<>();
                String[] audioFileUrls = sheetExport.getAudioFileUrls().split("[,，]");
                for (String audioFileUrl : audioFileUrls) {
                    MusicSheetAccompaniment musicSheetAccompaniment = new MusicSheetAccompaniment();
                    musicSheetAccompaniment.setAudioFileUrl(audioFileUrl);
                    background.add(musicSheetAccompaniment);
                }
                musicSheetDto.setBackground(background);
            }

            musicSheetDto.setMusicTag(musicTagIds.toString());

            musicSheetDtoList.add(musicSheetDto);
        }

        if (!CollectionUtils.isEmpty(errMsgList)) {
            throw new ExcelException("导入异常", errMsgList);
        }

        musicSheetDtoList.forEach(musicSheetDto -> saveMusicSheet(musicSheetDto, userId));

    }

    @Override
    public MusicSheetWebsiteDetailVo websiteDetail(Long musicSheetId, SysUser sysUser) {
        MusicSheetDetailVo detail = detail(musicSheetId, null, null);
        MusicSheetWebsiteDetailVo musicSheetWebsiteDetailVo = new MusicSheetWebsiteDetailVo();
        BeanUtils.copyProperties(detail, musicSheetWebsiteDetailVo);

        // 曲目收藏数
        long musicSheetFavoriteNum = musicFavoriteService.getMusicSheetFavoriteNum(musicSheetId);
        musicSheetWebsiteDetailVo.setFavoriteNum(musicSheetFavoriteNum);

        // 老师信息
        TeacherVo teacherVo = teacherService.detail(detail.getUserId());
        TeacherMusicSheetListVo teacherMusicSheetListVo = new TeacherMusicSheetListVo();
        teacherMusicSheetListVo.setUserAvatar(teacherVo.getAvatar());
        teacherMusicSheetListVo.setUserName(teacherVo.getUsername());
        teacherMusicSheetListVo.setUserId(teacherVo.getUserId());
        teacherMusicSheetListVo.setEntryFlag(teacherVo.getEntryFlag());
        teacherMusicSheetListVo.setMusicianFlag(teacherVo.getMusicianFlag());

        if (sysUser != null) {
            // 老师关注
            StudentStar studentStar = studentStarService.getByStudentIdAndTeacherId(sysUser.getId(), teacherVo.getUserId());
            if (studentStar != null) {
                teacherMusicSheetListVo.setStar(YesOrNoEnum.YES);
            }

            // 曲目收藏
            List<MusicFavorite> favorite = musicFavoriteService.getFavorite(sysUser.getId(), detail.getId());
            if (!CollectionUtils.isEmpty(favorite)) {
                musicSheetWebsiteDetailVo.setFavorite(YesOrNoEnum.YES);
            }
        }

        // 老师的曲目
        MusicSheetSearch musicSheetSearch = new MusicSheetSearch();
        musicSheetSearch.setCreateBy(teacherVo.getUserId());
        musicSheetSearch.setState(YesOrNoEnum.YES);
        musicSheetSearch.setAuditStatus(AuthStatusEnum.PASS);
        musicSheetSearch.setPage(1);
        musicSheetSearch.setRows(5);
        List<MusicSheetVo> musicSheetVos = baseMapper.selectPage(PageUtil.getPage(musicSheetSearch), musicSheetSearch);
        teacherMusicSheetListVo.setMusicSheetList(musicSheetVos);

        musicSheetWebsiteDetailVo.setTeacher(teacherMusicSheetListVo);
        return musicSheetWebsiteDetailVo;
    }

    @Override
    public TeacherAuditMusicSheetVo selectTeacherCount(Long userId) {
        return baseMapper.selectTeacherCount(userId);
    }

    @Override
    public List<TeacherTotalVo> queryTeacherTotal(Long userId) {
        return baseMapper.queryTeacherTotal(userId);
    }

    @Override
    public List<StudentTotalVo> queryStudentTotal(Long userId) {
        return baseMapper.queryStudentTotal(userId);
    }

    @Override
    public ShareProfitVo shareMusicSheetProfit(SysUser sysUser, Long musicSheetId) {
        ShareProfitVo result = new ShareProfitVo();
        MusicSheetDetailVo musicSheet = detail(musicSheetId,null,null);

        result.setTeacherId(sysUser.getId());
        result.setType("MUSIC");
        result.setMusicSheet(musicSheet);
        result.setAvatar(sysUser.getAvatar());
        result.setName(sysUser.getUsername());
        String teacherMusicShareProfitUrl= sysConfigService.findConfigValue(SysConfigConstant.TEACHER_MUSIC_SHEET_SHARE_PROFIT_URL);
        result.setUrl(MessageFormatter.arrayFormat(teacherMusicShareProfitUrl,musicSheetId, sysUser.getId()));
        return result;
    }

    private SysUser getSysUser(Long userId) {
        return Optional.ofNullable(userId)
                .map(sysUserFeignService::queryUserById)
                .orElseThrow(() -> new BizException("用户不存在"));
    }
}