package com.tangguo.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangguo.common.domain.PointsDetail;
import com.tangguo.common.exception.ServiceException;
import com.tangguo.domain.BbsPointsGoods;
import com.tangguo.domain.BbsUserPoints;
import com.tangguo.domain.BbsUserPointsExchange;
import com.tangguo.domain.bo.UserPointsExchangeBO;
import com.tangguo.mapper.BbsUserPointsExchangeMapper;
import com.tangguo.service.IBbsPointsGoodsService;
import com.tangguo.service.IBbsUserPointsExchangeService;
import com.tangguo.service.IBbsUserPointsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.*;

/**
 * 用户积分兑换Service业务层处理
 *
 * @author ruoyi
 * @date 2025-08-29
 */
@Slf4j
@Service
public class BbsUserPointsExchangeServiceImpl extends ServiceImpl<BbsUserPointsExchangeMapper, BbsUserPointsExchange> implements IBbsUserPointsExchangeService {

    @Resource
    private IBbsUserPointsService userPointsService;

    @Resource
    private IBbsPointsGoodsService pointsGoodsService;

	@Resource
	private TransactionTemplate transactionTemplate;


    /**
     * 查询用户积分兑换列表
     *
     * @param exchange 用户积分兑换
     * @return 用户积分兑换
     */
    @Override
    public List<BbsUserPointsExchange> selectBbsUserPointsExchangeList(BbsUserPointsExchange exchange) {
	    return this.baseMapper.selectBbsUserPointsExchangeList(exchange);
    }


    /**
     * 用户积分兑换
     *
     * @param exchange 兑换
     */
    @Override
    public void addUserPointsExchange(BbsUserPointsExchange exchange) {
		this.pointsExchange(exchange.getUserName(), exchange.getNickName(), exchange.getGoodsCode());
    }


	/**
	 * 批量用户积分兑换
	 *
	 * @param bo 兑换
	 */
	@Override
	public List<Map<String, String>> batchAddUserPointsExchange(UserPointsExchangeBO bo) {
		List<Map<String, String>> results = new ArrayList<>(10);
		for (UserPointsExchangeBO.User user : bo.getUsers()) {
			String userName = user.getUserName();
			String nickName = user.getNickName();
			try {
				this.pointsExchange(userName, nickName, bo.getGoodsCode());
			} catch (Exception e) {
				log.error("=> 批量用户积分兑换失败，用户：{} 商品：{} 失败原因：", userName, bo.getGoodsCode(), e);
				Map<String, String> resultItem = new HashMap<>(2);
				resultItem.put("nickName", nickName);
				resultItem.put("userName", userName);
				resultItem.put("errorMessage", e.getMessage());
				results.add(resultItem);
			}
		}
		return results;
	}


	/**
	 * 积分兑换
	 *
	 * @param userName 用户名
	 * @param goodsCode 商品编码
	 */
	public void pointsExchange(String userName, String nickName, String goodsCode) {
		synchronized (userName.intern()) {
			BbsPointsGoods dbGoods = this.pointsGoodsService.getByGoodsCode(goodsCode);
			if (Objects.isNull(dbGoods)) {
				throw new ServiceException("兑换失败，未查询到当前兑换的商品数据。");
			}
			if (dbGoods.getStockNum() < 1) {
				throw new ServiceException("兑换失败，当前兑换的商品库存数量不足。");
			}

			this.transactionTemplate.executeWithoutResult(status -> {
				try {
					// 用户积分校验
					Integer exchangePoints = dbGoods.getExchangePoints();
					BbsUserPoints dbUserPoints = this.userPointsService.getAndInitUserPoints(userName);
					int currentPoints = dbUserPoints.getCurrentPoints() - dbGoods.getExchangePoints();
					if (currentPoints < 0) {
						throw new ServiceException("兑换失败，当前用户可用积分不足。");
					}

					// 扣减商品库存
					Long goodsId = dbGoods.getId();
					boolean decrResult = this.pointsGoodsService.decrGoodsStock(goodsId, 1);
					if (!decrResult) {
						throw new ServiceException("兑换失败，当前兑换的商品库存数量不足。");
					}

					// 增加商品销量
					this.pointsGoodsService.incrGoodsSales(goodsId, 1);

					// 扣减用户积分
					PointsDetail detail = new PointsDetail();
					detail.setUserName(userName);
					detail.setDetailPoints(exchangePoints);
					detail.setDetailName(dbGoods.getName());
					detail.setDetailCode(dbGoods.getCode());
					detail.setDescription(String.format("用户【%s】兑换积分商品【%s-%s】", userName, dbGoods.getName(), dbGoods.getCode()));
					this.userPointsService.decrUserPoints(detail);

					// 添加兑换记录
					BbsUserPointsExchange addExchange = new BbsUserPointsExchange();
					addExchange.setNickName(nickName);
					addExchange.setUserName(userName);
					addExchange.setUserGradeName(dbUserPoints.getGradeName());
					addExchange.setGoodsName(dbGoods.getName());
					addExchange.setGoodsCode(dbGoods.getCode());
					addExchange.setGoodsExchangePoints(dbGoods.getExchangePoints());
					addExchange.setUserRemainingPoints(currentPoints);
					this.save(addExchange);

				} catch (Exception e) {
					log.error("=> 用户积分兑换失败：", e);
					status.setRollbackOnly();
					throw new ServiceException(e.getMessage());
				}
			});
		}
	}

}
