package org.dromara.ems.info.util;

import org.dromara.ems.info.domain.SparePartsInventory;
import org.dromara.ems.info.domain.SparePartsInventoryCheck;
import org.dromara.ems.info.mapper.SparePartsInventoryCheckMapper;
import org.dromara.ems.info.mapper.SparePartsInventoryMapper;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * 库存数量同步工具类
 * 负责在盘点记录变化时自动更新主表的剩余数量，确保数据一致性
 * 
 * @author system
 * @date 2025-01-10
 */
@Component
@RequiredArgsConstructor
public class InventoryQuantityUpdater 
{
    private static final Logger log = LoggerFactory.getLogger(InventoryQuantityUpdater.class);

    
    private final SparePartsInventoryMapper sparePartsInventoryMapper;
    
    
    private final SparePartsInventoryCheckMapper sparePartsInventoryCheckMapper;

    /**
     * 根据最新盘点记录更新主表剩余数量
     * 
     * @param inventoryObjid 库存记录ID
     */
    @Transactional
    public void updateRemainingQuantityByLatestCheck(Long inventoryObjid) {
        if (inventoryObjid == null) {
            return;
        }

        try {
            // 查询最新的盘点记录
            SparePartsInventoryCheck latestCheck = sparePartsInventoryCheckMapper.selectLatestCheckByInventoryObjid(inventoryObjid);
            
            // 查询主表记录
            SparePartsInventory inventory = sparePartsInventoryMapper.selectSparePartsInventoryByObjid(inventoryObjid);
            if (inventory == null) {
                return;
            }

            Long newRemainingQuantity = null;
            if (latestCheck != null && latestCheck.getCheckQuantity() != null) {
                // 如果有盘点记录，使用最新盘点数量
                newRemainingQuantity = latestCheck.getCheckQuantity();
            } else {
                // 如果没有盘点记录，使用入库数量作为剩余数量
                newRemainingQuantity = inventory.getWarehouseQuantity();
            }

            // 只有当剩余数量发生变化时才更新
            if (!isEqualQuantity(inventory.getRemainingQuantity(), newRemainingQuantity)) {
                SparePartsInventory updateInventory = new SparePartsInventory();
                updateInventory.setObjid(inventoryObjid);
                updateInventory.setRemainingQuantity(newRemainingQuantity);
                
                int updateResult = sparePartsInventoryMapper.updateSparePartsInventory(updateInventory);
                if (updateResult > 0) {
                    log.info("成功更新库存记录ID: {} 的剩余数量为: {}", inventoryObjid, newRemainingQuantity);
                } else {
                    log.error("更新库存记录ID: {} 的剩余数量失败", inventoryObjid);
                }
            } else {
                log.debug("库存记录ID: {} 的剩余数量无变化，跳过更新", inventoryObjid);
            }
            
        } catch (Exception e) {
            log.error("更新库存记录ID: {} 的剩余数量时发生异常", inventoryObjid, e);
            throw e; // 重新抛出异常以触发事务回滚
        }
    }

    /**
     * 比较两个数量是否相等（处理null值）
     */
    private boolean isEqualQuantity(Long quantity1, Long quantity2) {
        if (quantity1 == null && quantity2 == null) {
            return true;
        }
        if (quantity1 == null || quantity2 == null) {
            return false;
        }
        return quantity1.equals(quantity2);
    }

    /**
     * 批量更新多个库存记录的剩余数量
     * 
     * @param inventoryObjids 库存记录ID列表
     */
    @Transactional
    public void batchUpdateRemainingQuantity(Long[] inventoryObjids) {
        if (inventoryObjids == null || inventoryObjids.length == 0) {
            log.warn("库存记录ID列表为空，跳过批量更新");
            return;
        }

        log.info("开始批量更新 {} 个库存记录的剩余数量", inventoryObjids.length);
        int successCount = 0;
        int failureCount = 0;

        for (Long objid : inventoryObjids) {
            try {
                updateRemainingQuantityByLatestCheck(objid);
                successCount++;
            } catch (Exception e) {
                failureCount++;
                log.error("批量更新时处理库存记录ID: {} 失败", objid, e);
            }
        }

        log.info("批量更新完成，成功: {} 个，失败: {} 个", successCount, failureCount);
    }
} 
