package com.ym.mec.biz.service.impl;

import com.ym.mec.biz.dal.dao.LiveGoodsDao;
import com.ym.mec.biz.dal.dto.RedisKeyConstant;
import com.ym.mec.biz.dal.entity.LiveGoods;
import com.ym.mec.biz.dal.page.LiveGoodsQueryInfo;
import com.ym.mec.biz.service.LiveGoodsMapperService;
import com.ym.mec.biz.service.LiveGoodsService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;

@Service
public class LiveGoodsServiceImpl extends BaseServiceImpl<Integer, LiveGoods>  implements LiveGoodsService {
	
	@Autowired
	private LiveGoodsDao liveGoodsDao;
	@Autowired
	private LiveGoodsMapperService liveGoodsMapperService;
	@Autowired
	private RedissonClient redissonClient;

	@Override
	public BaseDAO<Integer, LiveGoods> getDAO() {
		return liveGoodsDao;
	}

    @Override
	@Transactional(rollbackFor = Exception.class)
    public void updateLiveGoods(LiveGoods liveGoods) {
		Optional.ofNullable(liveGoodsDao.get(liveGoods.getId())).orElseThrow(() -> new BizException("商品信息不存在"));
		//如果商品已在直播间上架，那么不允许变更商品信息
		if (liveGoodsMapperService.findByLiveGoodsIdAndStatus(liveGoods.getId(),true).size() > 0) {
			throw new BizException("商品已在直播间上架,不能修改");
		}
		//商品名称不能重复
		LiveGoods goodsDaoByName = liveGoodsDao.getByName(liveGoods.getName());
		if (goodsDaoByName != null && !goodsDaoByName.getId().equals(liveGoods.getId())) {
			throw new BizException("商品名称已存在");
		}
		//下架直播间商品,并通知直播间
//		if (!liveGoods.getStatus()) liveGoodsMapperService.downGoods(liveGoods.getId());
		//更新商品信息
		liveGoodsDao.update(liveGoods);
		//通知直播间
//		liveGoodsMapperService.downGoods(liveGoods.getId());
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteLiveGoods(Integer goodsId) {
		//如果商品没有被直播间使用,则删除商品
		if (liveGoodsMapperService.findByLiveGoodsIdAndStatus(goodsId,null).size() > 0) {
			throw new BizException("商品已被直播间使用,不能删除");
		}
		liveGoodsDao.delete(goodsId);
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public void initGoodsStockCache(Integer liveGoodsId, String liveId) {
		//更新缓存
		LiveGoods liveGoods = liveGoodsDao.getLock(liveGoodsId);
		if (liveGoods == null) throw new BizException("商品不存在");
		redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_STOCK_CACHE_KEY + liveId + liveGoodsId).set(liveGoods.getStockCount(),1, TimeUnit.DAYS);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void addGoodsStock(Integer liveGoodsId, String liveId) {
		liveGoodsDao.addStock(liveGoodsId);
//		RBucket<Integer> bucket = redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_STOCK_CACHE_KEY + liveId + liveGoodsId);
//		boolean exists = bucket.isExists();
//		if (exists) {
//			Integer frozenStock = bucket.get();
//			bucket.set(++frozenStock);
//		}else {
//			bucket.set(1);
//		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void reduceGoodsStock(Integer liveGoodsId, String liveId) {
		int i = liveGoodsDao.reduceStock(liveGoodsId);
		if (i == 0) throw new BizException("商品已售罄");
//		RBucket<Integer> bucket = redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_STOCK_CACHE_KEY + liveId + liveGoodsId);
//		boolean exists = bucket.isExists();
//		if (exists) {
//			Integer stock = bucket.get() - 1;
//			if (stock < 0) {
//				throw new BizException("哎呀，手慢了，商品已经卖完了");
//			}else if(stock == 0){
//				//如果库存为0，则定时删除缓存
//				bucket.set(stock,1,TimeUnit.HOURS);
//			}else {
//				bucket.set(stock);
//			}
//		}else {
//			LiveGoods liveGoods = liveGoodsDao.getLock(liveGoodsId);
//			redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_STOCK_CACHE_KEY + liveId + liveGoodsId).set(liveGoods.getStockCount(),1, TimeUnit.DAYS);
//		}
//		//增加冻结库存
//		this.addGoodsFreezeStock(liveGoodsId,liveId);
	}

	@Override
	public void addGoodsFreezeStock(Integer liveGoodsId, String liveId) {
		RBucket<Integer> bucket = redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_FROZEN_CACHE_KEY + liveId + liveGoodsId);
		boolean exists = bucket.isExists();
		if (exists) {
			Integer frozenStock = bucket.get();
			bucket.set(++frozenStock);
		}else {
			bucket.set(1);
		}
	}

	@Override
	public void reduceGoodsFreezeStock(Integer liveGoodsId, String liveId) {
		RBucket<Integer> bucket = redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_FROZEN_CACHE_KEY + liveId + liveGoodsId);
		boolean exists = bucket.isExists();
		if (exists) {
			Integer frozenStock = bucket.get() - 1;
			if (frozenStock < 0) {
				throw new BizException("订单库存扣减失败");
			}else if(frozenStock == 0){
				//如果冻结库存为0，则定时删除缓存
				bucket.set(frozenStock,1,TimeUnit.HOURS);
			}else {
				bucket.set(frozenStock);
			}
		}else {
			throw new BizException("订单库存扣减失败");
		}
	}

	@Override
	public Object queryGoodsPage(LiveGoodsQueryInfo queryInfo) {
		if(StringUtils.isNotEmpty(queryInfo.getLiveId())){
			//获取直播间关联的商品列表
			List<Integer> goodsIds = liveGoodsMapperService.queryGoodsIdsByLiveId(queryInfo.getLiveId());
			queryInfo.setIgnoreGoodsIds(goodsIds);
		}
		return queryPage(queryInfo);
	}

    @Override
	@Transactional(rollbackFor = Exception.class)
    public void add(LiveGoods liveGoods) {
		//商品名称不能重复
		LiveGoods goods = liveGoodsDao.getByName(liveGoods.getName());
		if (goods != null) throw new BizException("商品名称已存在");
		liveGoodsDao.insert(liveGoods);
    }

    public void stockLock(String lockKey, BiConsumer<Integer,String> consumer, Integer liveGoodsId, String liveId) {
		RLock lock = redissonClient.getLock(lockKey);
		try{
			lock.lock();
			consumer.accept(liveGoodsId,liveId);
		}catch(Exception e){
			e.printStackTrace();
		}finally {
			lock.unlock();
		}

	}

}