package com.erp.example.seata;

import com.erp.example.seata.entity.Inventory;
import com.erp.example.seata.entity.InventoryLog;
import com.erp.example.seata.mapper.InventoryLogMapper;
import com.erp.example.seata.mapper.InventoryMapper;
import io.seata.rm.tcc.api.BusinessActionContext;
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 java.time.LocalDateTime;

/**
 * 库存服务 - AT模式实现
 */
@Service
public class InventoryService {

    private static final Logger log = LoggerFactory.getLogger(InventoryService.class);

    @Autowired
    private InventoryMapper inventoryMapper;

    @Autowired
    private InventoryLogMapper inventoryLogMapper;

    /**
     * 预留库存（冻结库存）
     * AT模式自动记录前后镜像，异常时自动回滚
     */
    @Transactional
    public void reserveStock(Long productId, Integer quantity, String orderNo) {
        log.info("预留库存: 商品ID={}, 数量={}, 订单={}", productId, quantity, orderNo);
        
        Inventory inventory = inventoryMapper.findByProductId(productId);
        if (inventory == null) {
            throw new RuntimeException("商品不存在: " + productId);
        }
        
        Integer availableStock = inventory.getStock() - inventory.getReservedStock();
        if (availableStock < quantity) {
            throw new RuntimeException("库存不足: 可用=" + availableStock + ", 需要=" + quantity);
        }
        
        // 冻结库存 = 增加预留数量
        inventory.setReservedStock(inventory.getReservedStock() + quantity);
        inventoryMapper.update(inventory);
        
        // 记录库存变动日志
        InventoryLog log = new InventoryLog();
        log.setProductId(productId);
        log.setOrderNo(orderNo);
        log.setChangeType("RESERVE");
        log.setQuantity(quantity);
        log.setBeforeStock(inventory.getStock());
        log.setAfterStock(inventory.getStock());
        log.setCreateTime(LocalDateTime.now());
        inventoryLogMapper.insert(log);
        
        log.info("库存预留成功: {}", inventory);
    }

    /**
     * 释放库存（取消预留）
     * 用于订单取消时回滚
     */
    @Transactional
    public void releaseStock(Long productId, Integer quantity, String orderNo) {
        log.info("释放库存: 商品ID={}, 数量={}, 订单={}", productId, quantity, orderNo);
        
        Inventory inventory = inventoryMapper.findByProductId(productId);
        if (inventory == null) {
            log.warn("商品不存在: {}", productId);
            return;
        }
        
        // 释放库存 = 减少预留数量
        inventory.setReservedStock(Math.max(0, inventory.getReservedStock() - quantity));
        inventoryMapper.update(inventory);
        
        // 记录库存变动日志
        InventoryLog log = new InventoryLog();
        log.setProductId(productId);
        log.setOrderNo(orderNo);
        log.setChangeType("RELEASE");
        log.setQuantity(quantity);
        log.setBeforeStock(inventory.getStock());
        log.setAfterStock(inventory.getStock());
        log.setCreateTime(LocalDateTime.now());
        inventoryLogMapper.insert(log);
        
        log.info("库存释放成功: {}", inventory);
    }

    /**
     * 扣减库存（正式扣减，释放预留）
     * 订单支付成功后调用
     */
    @Transactional
    public void consumeStock(Long productId, Integer quantity, String orderNo) {
        log.info("扣减库存: 商品ID={}, 数量={}, 订单={}", productId, quantity, orderNo);
        
        Inventory inventory = inventoryMapper.findByProductId(productId);
        if (inventory == null) {
            throw new RuntimeException("商品不存在: " + productId);
        }
        
        // 扣减库存 = 减少总库存和预留库存
        inventory.setStock(inventory.getStock() - quantity);
        inventory.setReservedStock(inventory.getReservedStock() - quantity);
        inventoryMapper.update(inventory);
        
        // 记录库存变动日志
        InventoryLog inventoryLog = new InventoryLog();
        inventoryLog.setProductId(productId);
        inventoryLog.setOrderNo(orderNo);
        inventoryLog.setChangeType("CONSUME");
        inventoryLog.setQuantity(quantity);
        inventoryLog.setBeforeStock(inventory.getStock() + quantity);
        inventoryLog.setAfterStock(inventory.getStock());
        inventoryLog.setCreateTime(LocalDateTime.now());
        inventoryLogMapper.insert(inventoryLog);
        
        log.info("库存扣减成功: {}", inventory);
    }

    /**
     * 查询商品库存
     */
    public Inventory findByProductId(Long productId) {
        return inventoryMapper.findByProductId(productId);
    }
}
