package com.qs.mp.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qs.mp.admin.domain.CdKey;
import com.qs.mp.admin.domain.CdKeyExchange;
import com.qs.mp.admin.mapper.CdKeyExchangeMapper;
import com.qs.mp.admin.service.ICdKeyExchangeService;
import com.qs.mp.admin.service.ICdKeyService;
import com.qs.mp.admin.service.ICouponPkgService;
import com.qs.mp.admin.service.ICouponService;
import com.qs.mp.common.core.redis.DistributedLocker;
import com.qs.mp.common.enums.CdKeyGroupGoodsTypeEnum;
import com.qs.mp.common.enums.CoinLogTypeEnum;
import com.qs.mp.common.enums.PrizeStorageInTypeEnum;
import com.qs.mp.common.exception.ServiceException;
import com.qs.mp.core.domain.LoginUser;
import com.qs.mp.framework.redis.RedisLockKey;
import com.qs.mp.user.domain.UserCoin;
import com.qs.mp.user.domain.UserCoinLog;
import com.qs.mp.user.domain.vo.UserExchangeCdKeyVO;
import com.qs.mp.user.service.IUserCoinLogService;
import com.qs.mp.user.service.IUserCoinService;
import com.qs.mp.user.service.IUserPrizeStorageService;
import com.qs.mp.utils.SecurityUtils;
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 org.springframework.util.Assert;

import java.util.Date;

/**
 * @auther quanshu
 * @create 2023-05-16 17:21:23
 * @describe 兑换码兑换表服务实现类
 */
@Service
public class CdKeyExchangeServiceImpl extends ServiceImpl<CdKeyExchangeMapper, CdKeyExchange> implements ICdKeyExchangeService {

    private static final Logger logger = LoggerFactory.getLogger(CdKeyExchangeServiceImpl.class);

    @Autowired
    private IUserPrizeStorageService userPrizeStorageService;

    @Autowired
    private ICdKeyService cdKeyService;

    @Autowired
    private ICouponService couponService;

    @Autowired
    private ICouponPkgService couponPkgService;

    @Autowired
    private IUserCoinService userCoinService;

    @Autowired
    private DistributedLocker distributedLocker;

    @Autowired
    private IUserCoinLogService userCoinLogService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserExchangeCdKeyVO exchangeCdKey(Long keyId) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String LockKey = RedisLockKey.build(RedisLockKey.USER_CD_KEY_EXCHANGE_LOCK, loginUser.getUserId());
        if (!distributedLocker.tryLock(LockKey)) {
            throw new ServiceException("系统繁忙，请稍后再试");
        }
        UserExchangeCdKeyVO userExchangeCdKeyVO = null;
        try {
            // 更新兑换码状态
            boolean rst = cdKeyService.update(new UpdateWrapper<CdKey>().set("status", "1").eq("key_id", keyId));
            Assert.isTrue(rst, "更新兑换码状态失败");

            // 插入兑换记录
            CdKey cdKey = cdKeyService.getById(keyId);
            CdKeyExchange exchange = new CdKeyExchange();
            exchange.setGroupId(cdKey.getGroupId());
            exchange.setKeyId(String.valueOf(cdKey.getKeyId()));
            exchange.setUserId(loginUser.getUserId());
            exchange.setExchangeTime(new Date());
            save(exchange);

            // 分发对应商品
            if (CdKeyGroupGoodsTypeEnum.GOODS == cdKey.getType()) {
                userPrizeStorageService.takeInStorage(loginUser.getUserId(), cdKey.getGoodsName(), cdKey.getPicUrl(), cdKey.getRefId(), PrizeStorageInTypeEnum.CD_KEY_EXCHANGE, String.valueOf(exchange.getId()));
            }else if (CdKeyGroupGoodsTypeEnum.COUPON == cdKey.getType()) {
                couponService.distributeByCdKey(loginUser.getUserId(), cdKey.getRefId());
            } else if (CdKeyGroupGoodsTypeEnum.COUPON_PKG == cdKey.getType()) {
                couponPkgService.distributeByCdKey(loginUser.getUserId(), cdKey.getRefId());
            } else {
                UserCoin userCoin = userCoinService.getById(loginUser.getUserId());
                if (userCoin == null) {
                    // 用户从未获得过盲豆
                    UserCoin userNoCoin = new UserCoin();
                    userNoCoin.setCoin(cdKey.getValue());
                    userNoCoin.setUserId(loginUser.getUserId());
                    userNoCoin.setCreatedTime(new Date());
                    userNoCoin.setUpdatedTime(new Date());
                    boolean rtn2 = userCoinService.save(userNoCoin);
                    Assert.isTrue(rtn2, "从未获得过盲豆的用户通过兑换码兑换盲豆失败, userId:" + loginUser.getUserId());
                } else {
                    boolean rtn3 = userCoinService.update(new LambdaUpdateWrapper<UserCoin>().set(UserCoin::getCoin, userCoin.getCoin() + cdKey.getValue())
                            .eq(UserCoin::getUserId, loginUser.getUserId()));
                    Assert.isTrue(rtn3, "增加通过兑换码兑换盲豆失败，userId:" + loginUser.getUserId());
                }

                UserCoinLog userCoinToLog = new UserCoinLog();
                userCoinToLog.setUserId(loginUser.getUserId());
                userCoinToLog.setType(CoinLogTypeEnum.CD_KEPT);
                userCoinToLog.setMoney(userCoin == null ? cdKey.getValue() : userCoin.getCoin() + cdKey.getValue());
                userCoinToLog.setLogMoney(cdKey.getValue());
                userCoinToLog.setIncomeExpense(CoinLogTypeEnum.INCOME);
                userCoinToLog.setLogText("兑换码兑换");
                userCoinToLog.setBizTime(new Date());
                userCoinToLog.setCreatedTime(new Date());
                userCoinToLog.setUpdatedTime(new Date());
                userCoinLogService.save(userCoinToLog);
            }

            userExchangeCdKeyVO = new UserExchangeCdKeyVO();
            userExchangeCdKeyVO.setType(cdKey.getType().getValue());
            userExchangeCdKeyVO.setGoodsName(cdKey.getGoodsName());
            userExchangeCdKeyVO.setPicUrl(cdKey.getPicUrl());
            userExchangeCdKeyVO.setValue(cdKey.getValue());
        } catch (Exception e) {
            logger.error("兑换码兑换异常" + e.getMessage());
            throw new RuntimeException(e);
        } finally {
            distributedLocker.unlock(LockKey);
        }
        return userExchangeCdKeyVO;
    }
}
