package com.slodon.b2b2c.model.video;

import com.slodon.b2b2c.core.constant.GoodsConst;
import com.slodon.b2b2c.core.constant.VideoConst;
import com.slodon.b2b2c.core.exception.MallException;
import com.slodon.b2b2c.core.response.PagerInfo;
import com.slodon.b2b2c.core.util.AssertUtil;
import com.slodon.b2b2c.dao.read.goods.GoodsReadMapper;
import com.slodon.b2b2c.dao.read.video.*;
import com.slodon.b2b2c.dao.write.video.*;
import com.slodon.b2b2c.goods.pojo.Goods;
import com.slodon.b2b2c.video.example.*;
import com.slodon.b2b2c.video.pojo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;

/**
 * 短视频表model
 */
@Component
@Slf4j
public class SvideoVideoModel {

    @Resource
    private SvideoVideoReadMapper svideoVideoReadMapper;
    @Resource
    private SvideoVideoWriteMapper svideoVideoWriteMapper;
    @Resource
    private AuthorReadMapper authorReadMapper;
    @Resource
    private AuthorWriteMapper authorWriteMapper;
    @Resource
    private VideoGoodsReadMapper videoGoodsReadMapper;
    @Resource
    private VideoGoodsWriteMapper videoGoodsWriteMapper;
    @Resource
    private SvideoVideoLikeReadMapper svideoVideoLikeReadMapper;
    @Resource
    private SvideoVideoLikeWriteMapper svideoVideoLikeWriteMapper;
    @Resource
    private SvideoLabelReadMapper svideoLabelReadMapper;
    @Resource
    private SvideoCommentWriteMapper svideoCommentWriteMapper;
    @Resource
    private SvideoReplyWriteMapper svideoReplyWriteMapper;
    @Resource
    private VideoSettingReadMapper videoSettingReadMapper;
    @Resource
    private GoodsReadMapper goodsReadMapper;

    /**
     * 新增短视频表
     *
     * @param svideoVideo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer saveSvideoVideo(SvideoVideo svideoVideo, Author author, String goodsIds) {
        //查询标签信息
        SvideoLabel svideoLabel = svideoLabelReadMapper.getByPrimaryKey(svideoVideo.getLabelId());
        AssertUtil.notNull(svideoLabel, "视频标签不存在");
        svideoVideo.setLabelName(svideoLabel.getLabelName());
        svideoVideo.setAuthorId(author.getAuthorId());
        svideoVideo.setMemberName(author.getMemberName());
        svideoVideo.setMemberNickname(author.getMemberNickname());
        svideoVideo.setMemberAvatar(author.getMemberAvatar());
        int goodsNum = 0;
        if (StringUtils.isEmpty(goodsIds)) {
            svideoVideo.setGoodsNum(0);
        } else {
            goodsNum = goodsIds.split(",").length;
            //校验会员是否可以绑定商品
            AssertUtil.isTrue(!"1".equals(videoSettingReadMapper.getByPrimaryKey("member_bind_goods").getValue()), "不允许会员绑定商品");
            //校验会员绑定商品数量
            int bindGoodsNum = Integer.parseInt(videoSettingReadMapper.getByPrimaryKey("bind_goods_num").getValue());
            AssertUtil.isTrue(bindGoodsNum != 0 && goodsNum > bindGoodsNum, "视频最多可绑定" + bindGoodsNum + "件商品");
            svideoVideo.setGoodsNum(goodsNum);
        }
        int count = svideoVideoWriteMapper.insert(svideoVideo);
        if (count == 0) {
            throw new MallException("添加短视频表失败，请重试");
        }
        if (!StringUtils.isEmpty(goodsIds)) {
            String[] split = goodsIds.split(",");
            for (String goodsId : split) {
                if (StringUtils.isEmpty(goodsId)) {
                    continue;
                }
                //查询商品信息
                Goods goods = goodsReadMapper.getByPrimaryKey(Long.parseLong(goodsId));
                AssertUtil.notNull(goods, "商品不存在");
                AssertUtil.isTrue(!goods.getState().equals(GoodsConst.GOODS_STATE_UPPER), "该商品[" + goods.getGoodsName() + "]已下架");
                AssertUtil.isTrue(goods.getGoodsStock() == 0, "该商品[" + goods.getGoodsName() + "]库存不足");
                VideoGoods videoGoods = new VideoGoods();
                videoGoods.setVideoId(svideoVideo.getVideoId());
                videoGoods.setVideoType(VideoConst.VIDEO_TYPE_1);
                videoGoods.setAuthorId(author.getAuthorId());
                videoGoods.setGoodsId(Long.parseLong(goodsId));
                videoGoods.setGoodsName(goods.getGoodsName());
                videoGoods.setGoodsBrief(goods.getGoodsBrief());
                videoGoods.setGoodsPrice(goods.getGoodsPrice());
                videoGoods.setGoodsImage(goods.getMainImage());
                videoGoods.setDefaultProductId(goods.getDefaultProductId());
                count = videoGoodsWriteMapper.insert(videoGoods);
                AssertUtil.isTrue(count == 0, "保存视频商品失败，请重试");
            }
        }
        //更新作者绑定视频数以及视频绑定商品数
        Author authorNew = new Author();
        authorNew.setAuthorId(svideoVideo.getAuthorId());
        authorNew.setVideoNum(author.getVideoNum() + 1);
        authorNew.setGoodsNum(author.getGoodsNum() + goodsNum);
        authorNew.setUpdateTime(new Date());
        count = authorWriteMapper.updateByPrimaryKeySelective(authorNew);
        AssertUtil.isTrue(count == 0, "更新作者信息失败，请重试！");
        return count;
    }

    /**
     * 根据videoId删除短视频表
     *
     * @param videoId videoId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer deleteSvideoVideo(Integer videoId) {
        AssertUtil.notNullOrZero(videoId, "请选择要删除的数据");

        SvideoVideo svideoVideo = this.getSvideoVideoByVideoId(videoId);
        AssertUtil.notNull(svideoVideo, "获取视频信息为空，请重试");
//        AssertUtil.isTrue(svideoVideo.getState() != VideoConst.STATE_4, "只有禁止的视频才可以删除，请重试");

        SvideoVideo videoNew = new SvideoVideo();
        videoNew.setVideoId(videoId);
        videoNew.setState(VideoConst.STATE_5);
        videoNew.setIsDelete(VideoConst.IS_DELETE_1);
        Integer count = svideoVideoWriteMapper.updateByPrimaryKeySelective(videoNew);
        AssertUtil.isTrue(count == 0, "删除失败，请重试！");

        //删除视频评论
        SvideoCommentExample commentExample = new SvideoCommentExample();
        commentExample.setVideoId(videoId);
        svideoCommentWriteMapper.deleteByExample(commentExample);
        //删除视频回复
        SvideoReplyExample replyExample = new SvideoReplyExample();
        replyExample.setVideoId(videoId);
        svideoReplyWriteMapper.deleteByExample(replyExample);

        Author author = authorReadMapper.getByPrimaryKey(svideoVideo.getAuthorId());
        AssertUtil.notNull(author, "作者不存在");

        //根据videoId统计该视频绑定的商品数
        VideoGoodsExample example = new VideoGoodsExample();
        example.setVideoId(videoId);
        example.setVideoType(VideoConst.VIDEO_TYPE_1);
        example.setAuthorId(svideoVideo.getAuthorId());
        int goodsNum = videoGoodsReadMapper.countByExample(example);

        //更新作者绑定视频数以及视频绑定商品数
        Author authorNew = new Author();
        authorNew.setAuthorId(svideoVideo.getAuthorId());
        authorNew.setVideoNum(Integer.max(author.getVideoNum() - 1, 0));
        authorNew.setGoodsNum(Integer.max(author.getGoodsNum() - goodsNum, 0));
        authorNew.setUpdateTime(new Date());
        count = authorWriteMapper.updateByPrimaryKeySelective(authorNew);
        AssertUtil.isTrue(count == 0, "更新作者信息失败，请重试！");

        //删除视频绑定商品
        videoGoodsWriteMapper.deleteByExample(example);
        return count;
    }

    /**
     * 根据videoId更新短视频表
     *
     * @param svideoVideo
     * @return
     */
    public Integer updateSvideoVideo(SvideoVideo svideoVideo) {
        if (StringUtils.isEmpty(svideoVideo.getVideoId())) {
            throw new MallException("请选择要修改的数据");
        }
        int count = svideoVideoWriteMapper.updateByPrimaryKeySelective(svideoVideo);
        if (count == 0) {
            log.error("根据videoId：" + svideoVideo.getVideoId() + "更新短视频表失败");
            throw new MallException("更新短视频表失败,请重试");
        }
        return count;
    }

    /**
     * 重新编辑短视频
     *
     * @param svideoVideo
     * @param author
     * @param goodsIds
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer updateSvideoVideo(SvideoVideo svideoVideo, Author author, String goodsIds) {
        //查询数据库视频信息
        SvideoVideo svideoVideoDb = this.getSvideoVideoByVideoId(svideoVideo.getVideoId());
        AssertUtil.notNull(svideoVideoDb, "短视频不存在");
        if (svideoVideoDb.getVideoType() == VideoConst.SVIDEO_TYPE_2) {
            svideoVideo.setVideoThemeImage(svideoVideo.getVideoImage().split(",")[0]);
        }
        if (!svideoVideo.getLabelId().equals(svideoVideoDb.getLabelId())) {
            //查询标签信息
            SvideoLabel svideoLabel = svideoLabelReadMapper.getByPrimaryKey(svideoVideo.getLabelId());
            AssertUtil.notNull(svideoLabel, "视频标签不存在");
            svideoVideo.setLabelName(svideoLabel.getLabelName());
        }
        int goodsNum = 0;
        if (StringUtils.isEmpty(goodsIds)) {
            svideoVideo.setGoodsNum(0);
        } else {
            goodsNum = goodsIds.split(",").length;
            //校验会员是否可以绑定商品
            AssertUtil.isTrue(!"1".equals(videoSettingReadMapper.getByPrimaryKey("member_bind_goods").getValue()), "不允许会员绑定商品");
            //校验会员绑定商品数量
            int bindGoodsNum = Integer.parseInt(videoSettingReadMapper.getByPrimaryKey("bind_goods_num").getValue());
            AssertUtil.isTrue(bindGoodsNum != 0 && goodsNum > bindGoodsNum, "视频最多可绑定" + bindGoodsNum + "件商品");
            svideoVideo.setGoodsNum(goodsNum);
        }
        int count = svideoVideoWriteMapper.updateByPrimaryKeySelective(svideoVideo);
        AssertUtil.isTrue(count == 0, "更新短视频失败，请重试");

        //删除绑定视频，重新插入
        VideoGoodsExample example = new VideoGoodsExample();
        example.setVideoId(svideoVideo.getVideoId());
        example.setVideoType(VideoConst.VIDEO_TYPE_1);
        videoGoodsWriteMapper.deleteByExample(example);
        if (!StringUtils.isEmpty(goodsIds)) {
            String[] split = goodsIds.split(",");
            for (String goodsId : split) {
                if (StringUtils.isEmpty(goodsId)) {
                    continue;
                }
                //查询商品信息
                Goods goods = goodsReadMapper.getByPrimaryKey(Long.parseLong(goodsId));
                AssertUtil.notNull(goods, "商品不存在");
                VideoGoods videoGoods = new VideoGoods();
                videoGoods.setVideoId(svideoVideo.getVideoId());
                videoGoods.setVideoType(VideoConst.VIDEO_TYPE_1);
                videoGoods.setAuthorId(author.getAuthorId());
                videoGoods.setGoodsId(Long.parseLong(goodsId));
                videoGoods.setGoodsName(goods.getGoodsName());
                videoGoods.setGoodsBrief(goods.getGoodsBrief());
                videoGoods.setGoodsPrice(goods.getGoodsPrice());
                videoGoods.setGoodsImage(goods.getMainImage());
                videoGoods.setDefaultProductId(goods.getDefaultProductId());
                count = videoGoodsWriteMapper.insert(videoGoods);
                AssertUtil.isTrue(count == 0, "保存视频商品失败，请重试");
            }
        }
        //更新作者视频绑定商品数
        Author authorNew = new Author();
        authorNew.setAuthorId(author.getAuthorId());
        authorNew.setGoodsNum(Integer.max(author.getGoodsNum() - svideoVideoDb.getGoodsNum() + goodsNum, 0));
        authorNew.setUpdateTime(new Date());
        count = authorWriteMapper.updateByPrimaryKeySelective(authorNew);
        AssertUtil.isTrue(count == 0, "更新作者绑定商品数信息失败，请重试！");
        return count;
    }

    /**
     * 根据videoId获取短视频表详情
     *
     * @param videoId videoId
     * @return
     */
    public SvideoVideo getSvideoVideoByVideoId(Integer videoId) {
        return svideoVideoReadMapper.getByPrimaryKey(videoId);
    }

    /**
     * 根据条件获取短视频表列表
     *
     * @param example 查询条件信息
     * @param pager   分页信息
     * @return
     */
    public List<SvideoVideo> getSvideoVideoList(SvideoVideoExample example, PagerInfo pager) {
        List<SvideoVideo> svideoVideoList;
        if (pager != null) {
            pager.setRowsCount(svideoVideoReadMapper.countByExample(example));
            svideoVideoList = svideoVideoReadMapper.listPageByExample(example, pager.getStart(), pager.getPageSize());
        } else {
            svideoVideoList = svideoVideoReadMapper.listByExample(example);
        }
        return svideoVideoList;
    }

    /**
     * 根据条件获取短视频表列表数量
     *
     * @param example 查询条件信息
     * @return
     */
    public Integer getSvideoVideoCount(SvideoVideoExample example) {
        return svideoVideoReadMapper.countByExample(example);
    }

    /**
     * 视频点赞
     *
     * @param videoId
     * @param author
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String clickPraise(Integer videoId, Author author) {
        //查询是否有历史点赞记录
        SvideoVideoLikeExample example = new SvideoVideoLikeExample();
        example.setAuthorId(author.getAuthorId());
        example.setVideoId(videoId);
        List<SvideoVideoLike> videoLikeList = svideoVideoLikeReadMapper.listByExample(example);
        SvideoVideo svideoVideo = this.getSvideoVideoByVideoId(videoId);
        AssertUtil.notNull(svideoVideo, "视频不存在");
        //查询视频作者信息
        Author videoAuthor = authorReadMapper.getByPrimaryKey(svideoVideo.getAuthorId());
        AssertUtil.notNull(videoAuthor, "视频作者不存在");
        AssertUtil.isTrue(svideoVideo.getState() == VideoConst.STATE_1 || svideoVideo.getState() == VideoConst.STATE_3, "该作品还未审核通过，不允许该操作");
        AssertUtil.isTrue(svideoVideo.getState() == VideoConst.STATE_4, "该作品已被下架，不允许该操作");
        int count = 0;
        SvideoVideo video = new SvideoVideo();
        if (CollectionUtils.isEmpty(videoLikeList)) {
            //没有点赞历史 直接插入
            SvideoVideoLike record = new SvideoVideoLike();
            record.setVideoId(videoId);
            record.setAuthorId(author.getAuthorId());
            count = svideoVideoLikeWriteMapper.insert(record);
            AssertUtil.isTrue(count == 0, "点赞失败，请重试！");

            //更新视频点赞数量
            video.setVideoId(videoId);
            video.setLikeNum(svideoVideo.getLikeNum() + 1);
            video.setUpdateTime(new Date());
            count = svideoVideoWriteMapper.updateByPrimaryKeySelective(video);
            AssertUtil.isTrue(count == 0, "更新视频点赞数量失败，请重试！");

            //更新点赞视频数
            Author authorNew = new Author();
            authorNew.setAuthorId(author.getAuthorId());
            authorNew.setLikeVideoNum(author.getLikeVideoNum() + 1);
            authorNew.setUpdateTime(new Date());
            count = authorWriteMapper.updateByPrimaryKeySelective(authorNew);
            AssertUtil.isTrue(count == 0, "更新作者点赞视频数量失败，请重试！");

            //更新获赞总数
            Author authorLike = new Author();
            authorLike.setAuthorId(videoAuthor.getAuthorId());
            authorLike.setLikeNum(videoAuthor.getLikeNum() + 1);
            authorLike.setUpdateTime(new Date());
            count = authorWriteMapper.updateByPrimaryKeySelective(authorLike);
            AssertUtil.isTrue(count == 0, "更新作者点赞视频数量失败，请重试！");
        } else {
            SvideoVideoLike like = videoLikeList.get(0);
            //点赞两次相当于直接取消
            count = svideoVideoLikeWriteMapper.deleteByPrimaryKey(like.getVideoLikeId());
            AssertUtil.isTrue(count == 0, "取消点赞失败，请重试！");

            //更新视频点赞数量
            video.setVideoId(videoId);
            video.setLikeNum(Integer.max(svideoVideo.getLikeNum() - 1, 0));
            video.setUpdateTime(new Date());
            count = svideoVideoWriteMapper.updateByPrimaryKeySelective(video);
            AssertUtil.isTrue(count == 0, "更新视频点赞数量失败，请重试！");

            //更新点赞视频数
            Author authorNew = new Author();
            authorNew.setAuthorId(author.getAuthorId());
            authorNew.setLikeVideoNum(Integer.max(author.getLikeVideoNum() - 1, 0));
            authorNew.setUpdateTime(new Date());
            count = authorWriteMapper.updateByPrimaryKeySelective(authorNew);
            AssertUtil.isTrue(count == 0, "更新作者点赞视频数量失败，请重试！");

            //更新获赞总数
            Author authorLike = new Author();
            authorLike.setAuthorId(videoAuthor.getAuthorId());
            authorLike.setLikeNum(Integer.max(videoAuthor.getLikeNum() - 1, 0));
            authorLike.setUpdateTime(new Date());
            count = authorWriteMapper.updateByPrimaryKeySelective(authorLike);
            AssertUtil.isTrue(count == 0, "更新作者点赞视频数量失败，请重试！");
        }
        return video.getLikeNum() < 10000 ? video.getLikeNum().toString()
                : new BigDecimal(video.getLikeNum()).divide(new BigDecimal(10000), 1, RoundingMode.FLOOR) + "w";
    }
}