package com.fjhx.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.constants.ErrorMsgConstant;
import com.fjhx.constants.LibraryStorageLockConstant;
import com.fjhx.constants.StockJournalTypeConstant;
import com.fjhx.entity.Stock;
import com.fjhx.mapper.StockMapper;
import com.fjhx.service.StockService;
import com.fjhx.utils.Assert;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.redis.lock.RedisLockClient;
import org.springblade.core.secure.utils.AuthUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;

/**
 * <p>
 * 库存 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-08-10
 */
@Service
public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements StockService {

    @Resource
    private RedisLockClient redisLockClient;

    @Autowired
    private StockJournalServiceImpl stockJournalService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void changeQuantity(Long goodsId, Long warehouseId, BigDecimal quantity, Integer detailsType, String remarks) {

        // 分布式锁，粒度为物品id + 仓库id
        Boolean flag = redisLockClient.lockFair(LibraryStorageLockConstant.STOCK_LOCK + goodsId + warehouseId,
                () -> {

                    Stock stock = getOne(Wrappers.<Stock>lambdaQuery()
                            .eq(Stock::getGoodsId, goodsId)
                            .eq(Stock::getWarehouseId, warehouseId));

                    // 没有物料存储记录，则创建物料
                    if (stock == null) {
                        stock = new Stock();
                        stock.setGoodsId(goodsId);
                        stock.setQuantity(quantity);
                        stock.setWarehouseId(warehouseId);
                        stock.setTenantId(AuthUtil.getTenantId());
                        save(stock);
                        return true;
                    }

                    BigDecimal oldQuantity = stock.getQuantity();
                    BigDecimal newQuantity = oldQuantity.add(quantity);

                    int compareTo = newQuantity.compareTo(BigDecimal.ZERO);

                    if (compareTo < 0) {
                        throw new ServiceException("库存不足，出库失败");
                    }

                    // 如果出库之后等于0，删除记录
                    if (compareTo == 0) {
                        remove(Stock::getGoodsId, goodsId);
                        return true;
                    }

                    stock.setQuantity(newQuantity);
                    updateById(stock);

                    return true;
                });

        Assert.eqTrue(flag, ErrorMsgConstant.SYSTEM_BUSY_ERROR);


        // 添加出入库明细
        stockJournalService.add(
                quantity.compareTo(BigDecimal.ZERO) > 0 ? StockJournalTypeConstant.IN : StockJournalTypeConstant.OUT,
                detailsType,
                goodsId,
                warehouseId,
                quantity.compareTo(BigDecimal.ZERO) > 0 ? quantity : BigDecimal.ZERO.subtract(quantity),
                remarks
        );

    }

}
