package com.erp.inventory.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.erp.inventory.dto.*;
import com.erp.inventory.entity.Stock;
import com.erp.inventory.entity.StockLog;
import com.erp.inventory.entity.Warehouse;
import com.erp.inventory.event.StockChangedEvent;
import com.erp.inventory.repository.StockLogRepository;
import com.erp.inventory.repository.StockRepository;
import com.erp.inventory.repository.WarehouseRepository;
import com.erp.inventory.service.StockCheckService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.erp.common.core.model.PageResponse;

/**
 * 库存盘点服务实现
 * 对应PHP StockController + StockService
 * 
 * @author ERP Migration
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class StockCheckServiceImpl implements StockCheckService {

    private final StockRepository stockRepository;
    private final StockLogRepository stockLogRepository;
    private final WarehouseRepository warehouseRepository;
    private final ApplicationEventPublisher eventPublisher;

    // ==================== 库存查询 ====================

    @Override
    public PageResponse<StockListItemDTO> listStocks(StockQueryDTO query) {
        Page<Stock> page = new Page<>(query.getPage(), query.getLimit());
        IPage<Stock> stockPage = stockRepository.findByConditions(
                page,
                query.getSkuCode(),
                query.getSkuName(),
                query.getWarehouseId(),
                query.getLowStock()
        );

        // 获取仓库名称映射
        List<Long> warehouseIds = stockPage.getRecords().stream()
                .map(Stock::getWarehouseId)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, String> warehouseNameMap = getWarehouseNameMap(warehouseIds);

        // 转换为DTO
        List<StockListItemDTO> dtoList = stockPage.getRecords().stream()
                .map(stock -> toStockListItemDTO(stock, warehouseNameMap))
                .collect(Collectors.toList());

        return PageResponse.of(dtoList, stockPage.getTotal(), query.getPage(), query.getLimit());
    }

    @Override
    public StockDetailDTO getStockDetail(String skuCode, Long warehouseId) {
        Stock stock = stockRepository.findBySkuCodeAndWarehouseId(skuCode, warehouseId);
        if (stock == null) {
            throw new RuntimeException("库存记录不存在");
        }

        String warehouseName = warehouseRepository.findNameById(warehouseId);

        return StockDetailDTO.builder()
                .skuCode(stock.getSkuCode())
                .skuName(stock.getSkuName())
                .warehouseId(stock.getWarehouseId())
                .warehouseName(warehouseName)
                .quantity(stock.getQuantity())
                .lockedQuantity(stock.getLockedQuantity())
                .availableQuantity(stock.getAvailableQuantity())
                .defectiveQuantity(stock.getDefectiveQuantity())
                .warningThreshold(stock.getWarningThreshold())
                .build();
    }

    // ==================== 库存盘点调整 ====================

    @Override
    @Transactional
    public StockAdjustResponse adjustStock(StockAdjustRequest request) {
        // 获取或创建库存记录
        Stock stock = getOrCreateStock(request.getSkuCode(), request.getWarehouseId());

        // 记录原始数量用于日志
        Integer oldQuantity = stock.getQuantity();
        Integer oldLockedQuantity = stock.getLockedQuantity();
        Integer oldDefectiveQuantity = stock.getDefectiveQuantity();

        // 更新库存数量
        if (request.getQuantity() != null) {
            stock.setQuantity(request.getQuantity());
        }
        if (request.getLockedQuantity() != null) {
            stock.setLockedQuantity(request.getLockedQuantity());
        }
        if (request.getDefectiveQuantity() != null) {
            stock.setDefectiveQuantity(request.getDefectiveQuantity());
        }

        stockRepository.updateById(stock);

        // 创建调整日志
        String remark = buildAdjustRemark(request, oldQuantity, oldLockedQuantity, oldDefectiveQuantity);
        createStockLog(
                request.getSkuCode(),
                request.getWarehouseId(),
                stock.getQuantity() - oldQuantity, // 变化量
                StockLog.Type.ADJUST.getCode(),
                null,
                remark
        );

        log.info("库存盘点调整成功: skuCode={}, warehouseId={}, oldQuantity={}, newQuantity={}",
                request.getSkuCode(), request.getWarehouseId(), oldQuantity, stock.getQuantity());

        // 发布库存变更事件，触发预警检查
        if (!stock.getQuantity().equals(oldQuantity)) {
            publishStockChangedEvent(stock, "adjust", stock.getQuantity() - oldQuantity, oldQuantity, stock.getQuantity());
        }

        return StockAdjustResponse.builder()
                .quantity(stock.getQuantity())
                .lockedQuantity(stock.getLockedQuantity())
                .defectiveQuantity(stock.getDefectiveQuantity())
                .build();
    }

    private String buildAdjustRemark(StockAdjustRequest request, Integer oldQty, Integer oldLock, Integer oldDef) {
        StringBuilder sb = new StringBuilder("盘点校准");
        if (request.getQuantity() != null && !request.getQuantity().equals(oldQty)) {
            sb.append(", 库存: ").append(oldQty).append("->").append(request.getQuantity());
        }
        if (request.getLockedQuantity() != null && !request.getLockedQuantity().equals(oldLock)) {
            sb.append(", 锁定: ").append(oldLock).append("->").append(request.getLockedQuantity());
        }
        if (request.getDefectiveQuantity() != null && !request.getDefectiveQuantity().equals(oldDef)) {
            sb.append(", 残次: ").append(oldDef).append("->").append(request.getDefectiveQuantity());
        }
        if (request.getRemark() != null && !request.getRemark().isEmpty()) {
            sb.append(", 备注: ").append(request.getRemark());
        }
        return sb.toString();
    }

    // ==================== 手动入库/出库 ====================

    @Override
    @Transactional
    public Stock adjustForInbound(StockInboundRequest request) {
        if (request.getQuantity() <= 0) {
            throw new IllegalArgumentException("入库数量必须为正数");
        }

        Stock stock = getOrCreateStock(request.getSkuCode(), request.getWarehouseId());
        int oldQuantity = stock.getQuantity();

        // 增加库存
        stock.setQuantity(stock.getQuantity() + request.getQuantity());
        stockRepository.updateById(stock);

        // 创建入库日志
        String remark = buildInboundRemark(request);
        createStockLog(
                request.getSkuCode(),
                request.getWarehouseId(),
                request.getQuantity(),
                StockLog.Type.INBOUND.getCode(),
                null,
                remark
        );

        log.info("手动入库成功: skuCode={}, warehouseId={}, quantity={}, newTotal={}",
                request.getSkuCode(), request.getWarehouseId(), request.getQuantity(), stock.getQuantity());

        // 发布库存变更事件，触发预警检查
        publishStockChangedEvent(stock, "inbound", request.getQuantity(), oldQuantity, stock.getQuantity());

        return stock;
    }

    private String buildInboundRemark(StockInboundRequest request) {
        StringBuilder sb = new StringBuilder("手动入库");
        if (request.getRelatedNo() != null && !request.getRelatedNo().isEmpty()) {
            sb.append(", 关联单号: ").append(request.getRelatedNo());
        }
        if (request.getRemark() != null && !request.getRemark().isEmpty()) {
            sb.append(", 备注: ").append(request.getRemark());
        }
        return sb.toString();
    }

    @Override
    @Transactional
    public Stock adjustForOutbound(StockOutboundRequest request) {
        if (request.getQuantity() <= 0) {
            throw new IllegalArgumentException("出库数量必须为正数");
        }

        Stock stock = getOrCreateStock(request.getSkuCode(), request.getWarehouseId());

        // 检查可用库存
        if (stock.getAvailableQuantity() < request.getQuantity()) {
            throw new RuntimeException(String.format(
                    "商品 %s 可用库存不足，当前可用%d，需出库%d",
                    request.getSkuCode(), stock.getAvailableQuantity(), request.getQuantity()));
        }

        int oldQuantity = stock.getQuantity();

        // 扣减库存
        stock.setQuantity(stock.getQuantity() - request.getQuantity());
        stockRepository.updateById(stock);

        // 创建出库日志
        String remark = buildOutboundRemark(request);
        createStockLog(
                request.getSkuCode(),
                request.getWarehouseId(),
                -request.getQuantity(),
                StockLog.Type.OUTBOUND.getCode(),
                null,
                remark
        );

        log.info("手动出库成功: skuCode={}, warehouseId={}, quantity={}, newTotal={}",
                request.getSkuCode(), request.getWarehouseId(), request.getQuantity(), stock.getQuantity());

        // 发布库存变更事件，触发预警检查
        publishStockChangedEvent(stock, "outbound", -request.getQuantity(), oldQuantity, stock.getQuantity());

        return stock;
    }

    private String buildOutboundRemark(StockOutboundRequest request) {
        StringBuilder sb = new StringBuilder("手动出库");
        if (request.getRelatedNo() != null && !request.getRelatedNo().isEmpty()) {
            sb.append(", 关联单号: ").append(request.getRelatedNo());
        }
        if (request.getRemark() != null && !request.getRemark().isEmpty()) {
            sb.append(", 备注: ").append(request.getRemark());
        }
        return sb.toString();
    }

    @Override
    @Transactional
    public void defectiveInbound(DefectiveInboundRequest request) {
        if (request.getQuantity() <= 0) {
            throw new IllegalArgumentException("残次品入库数量必须为正数");
        }

        Stock stock = getOrCreateStock(request.getSkuCode(), request.getWarehouseId());

        // 增加残次品数量
        stock.setDefectiveQuantity(stock.getDefectiveQuantity() + request.getQuantity());
        stockRepository.updateById(stock);

        // 创建残次品入库日志
        String remark = buildDefectiveRemark(request);
        createStockLog(
                request.getSkuCode(),
                request.getWarehouseId(),
                request.getQuantity(),
                StockLog.Type.DEFECTIVE_INBOUND.getCode(),
                request.getOrderId(),
                remark
        );

        log.info("残次品入库成功: skuCode={}, warehouseId={}, quantity={}",
                request.getSkuCode(), request.getWarehouseId(), request.getQuantity());
    }

    private String buildDefectiveRemark(DefectiveInboundRequest request) {
        StringBuilder sb = new StringBuilder("残次品入库");
        if (request.getRelatedNo() != null && !request.getRelatedNo().isEmpty()) {
            sb.append(", 关联单号: ").append(request.getRelatedNo());
        }
        if (request.getOrderId() != null) {
            sb.append(", 订单ID: ").append(request.getOrderId());
        }
        if (request.getRemark() != null && !request.getRemark().isEmpty()) {
            sb.append(", 备注: ").append(request.getRemark());
        }
        return sb.toString();
    }

    // ==================== 库存流水 ====================

    @Override
    public PageResponse<StockLogDTO> listStockLogs(StockLogQueryDTO query) {
        Page<StockLog> page = new Page<>(query.getPage(), query.getLimit());

        // 解析日期
        LocalDateTime startDateTime = null;
        LocalDateTime endDateTime = null;
        if (query.getStartDate() != null && !query.getStartDate().isEmpty()) {
            startDateTime = LocalDateTime.parse(query.getStartDate() + " 00:00:00", 
                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        }
        if (query.getEndDate() != null && !query.getEndDate().isEmpty()) {
            endDateTime = LocalDateTime.parse(query.getEndDate() + " 23:59:59",
                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        }

        IPage<StockLog> logPage = stockLogRepository.findByConditions(
                page,
                query.getSkuCode(),
                query.getWarehouseId(),
                query.getType(),
                query.getOrderId(),
                query.getDeliveryNo(),
                startDateTime,
                endDateTime
        );

        // 获取仓库名称映射
        List<Long> warehouseIds = logPage.getRecords().stream()
                .map(StockLog::getWarehouseId)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, String> warehouseNameMap = getWarehouseNameMap(warehouseIds);

        // 转换为DTO
        List<StockLogDTO> dtoList = logPage.getRecords().stream()
                .map(log -> toStockLogDTO(log, warehouseNameMap))
                .collect(Collectors.toList());

        return PageResponse.of(dtoList, logPage.getTotal(), query.getPage(), query.getLimit());
    }

    // ==================== 预警管理 ====================

    @Override
    public Stock updateThreshold(UpdateThresholdRequest request) {
        Stock stock = getOrCreateStock(request.getSkuCode(), request.getWarehouseId());
        stock.setWarningThreshold(request.getWarningThreshold());
        stockRepository.updateById(stock);

        log.info("更新预警阈值成功: skuCode={}, warehouseId={}, threshold={}",
                request.getSkuCode(), request.getWarehouseId(), request.getWarningThreshold());

        return stock;
    }

    @Override
    public PageResponse<StockWarningDTO> listStockWarnings(Long warehouseId, Integer page, Integer limit) {
        Page<Stock> stockPage = new Page<>(page, limit);
        IPage<Stock> warningPage = stockRepository.findLowStockWarnings(stockPage, warehouseId);

        // 获取仓库名称映射
        List<Long> warehouseIds = warningPage.getRecords().stream()
                .map(Stock::getWarehouseId)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, String> warehouseNameMap = getWarehouseNameMap(warehouseIds);

        // 转换为DTO
        List<StockWarningDTO> dtoList = warningPage.getRecords().stream()
                .map(stock -> toStockWarningDTO(stock, warehouseNameMap))
                .collect(Collectors.toList());

        return PageResponse.of(dtoList, warningPage.getTotal(), page, limit);
    }

    // ==================== 锁定/解锁 ====================

    @Override
    @Transactional
    public Stock lockStock(String skuCode, Long warehouseId, Integer quantity, Long orderId) {
        if (quantity <= 0) {
            throw new IllegalArgumentException("占用数量必须为正数");
        }

        Stock stock = getOrCreateStock(skuCode, warehouseId);
        if (stock.getAvailableQuantity() < quantity) {
            throw new RuntimeException(String.format(
                    "商品 %s 可用库存不足，当前可用%d，需占用%d",
                    skuCode, stock.getAvailableQuantity(), quantity));
        }

        // 增加锁定库存
        stock.setLockedQuantity(stock.getLockedQuantity() + quantity);
        stockRepository.updateById(stock);

        // 创建锁定日志
        createStockLog(skuCode, warehouseId, quantity, StockLog.Type.LOCK.getCode(), orderId,
                "锁定库存，订单ID " + orderId);

        log.info("锁定库存成功: skuCode={}, warehouseId={}, quantity={}, orderId={}",
                skuCode, warehouseId, quantity, orderId);

        return stock;
    }

    @Override
    @Transactional
    public Stock unlockStock(String skuCode, Long warehouseId, Integer quantity, Long orderId) {
        if (quantity <= 0) {
            throw new IllegalArgumentException("解锁数量必须为正数");
        }

        Stock stock = getOrCreateStock(skuCode, warehouseId);
        if (stock.getLockedQuantity() < quantity) {
            throw new RuntimeException(String.format(
                    "商品 %s 锁定库存不足，当前锁定%d，需解锁%d",
                    skuCode, stock.getLockedQuantity(), quantity));
        }

        // 减少锁定库存
        stock.setLockedQuantity(stock.getLockedQuantity() - quantity);
        stockRepository.updateById(stock);

        // 创建解锁日志
        createStockLog(skuCode, warehouseId, -quantity, StockLog.Type.UNLOCK.getCode(), orderId,
                "解锁库存，订单ID " + orderId);

        log.info("解锁库存成功: skuCode={}, warehouseId={}, quantity={}, orderId={}",
                skuCode, warehouseId, quantity, orderId);

        return stock;
    }

    @Override
    public Integer checkAvailableStock(String skuCode, Long warehouseId) {
        Stock stock = stockRepository.findBySkuCodeAndWarehouseId(skuCode, warehouseId);
        if (stock == null) {
            return 0;
        }
        return stock.getAvailableQuantity();
    }

    // ==================== 预扣库存（两阶段模式） ====================

    @Override
    @Transactional
    public StockReserveResponse reserveStock(String skuCode, Long warehouseId, Integer quantity, Long orderId) {
        if (quantity <= 0) {
            throw new IllegalArgumentException("预扣数量必须为正数");
        }

        Stock stock = getOrCreateStock(skuCode, warehouseId);
        if (stock.getAvailableQuantity() < quantity) {
            throw new RuntimeException(String.format(
                    "商品 %s 可用库存不足，当前可用%d，需预扣%d",
                    skuCode, stock.getAvailableQuantity(), quantity));
        }

        // 增加预扣库存
        stock.setReservedQuantity(stock.getReservedQuantity() + quantity);
        stockRepository.updateById(stock);

        // 生成预扣凭证
        String reserveToken = generateReserveToken(orderId, skuCode);

        // 创建预扣日志
        createStockLog(skuCode, warehouseId, quantity, StockLog.Type.RESERVE.getCode(), orderId,
                String.format("预扣库存，订单ID %d，凭证 %s", orderId, reserveToken));

        log.info("预扣库存成功: skuCode={}, warehouseId={}, quantity={}, orderId={}, token={}",
                skuCode, warehouseId, quantity, orderId, reserveToken);

        return new StockReserveResponse(stock, reserveToken);
    }

    @Override
    @Transactional
    public Stock confirmReserve(String reserveToken, Long orderId, String trackingNo) {
        if (reserveToken == null || reserveToken.isEmpty()) {
            throw new IllegalArgumentException("预扣凭证不能为空");
        }

        // 查找预扣记录
        StockLog reserveLog = stockLogRepository.findByReserveToken(reserveToken, orderId);
        if (reserveLog == null) {
            throw new RuntimeException("找不到预扣凭证 " + reserveToken + " 的记录");
        }

        String skuCode = reserveLog.getSkuCode();
        Long warehouseId = reserveLog.getWarehouseId();
        int quantity = Math.abs(reserveLog.getChangeQuantity());

        Stock stock = stockRepository.findBySkuCodeAndWarehouseId(skuCode, warehouseId);
        if (stock == null) {
            throw new RuntimeException("库存记录不存在");
        }

        if (stock.getReservedQuantity() < quantity) {
            throw new RuntimeException(String.format(
                    "预扣库存不足，无法确认。当前预扣%d，需确认%d",
                    stock.getReservedQuantity(), quantity));
        }

        // 确认：预扣减，库存减（实际出库）
        stock.setReservedQuantity(stock.getReservedQuantity() - quantity);
        stock.setQuantity(stock.getQuantity() - quantity);
        stockRepository.updateById(stock);

        // 创建确认日志
        createStockLog(skuCode, warehouseId, -quantity, StockLog.Type.CONFIRM.getCode(), orderId,
                String.format("确认预扣出库，凭证 %s，运单号 %s", reserveToken, trackingNo));

        log.info("确认预扣成功: token={}, orderId={}, quantity={}, trackingNo={}",
                reserveToken, orderId, quantity, trackingNo);

        return stock;
    }

    @Override
    @Transactional
    public Stock cancelReserve(String reserveToken, Long orderId) {
        if (reserveToken == null || reserveToken.isEmpty()) {
            throw new IllegalArgumentException("预扣凭证不能为空");
        }

        // 查找预扣记录
        StockLog reserveLog = stockLogRepository.findByReserveToken(reserveToken, orderId);
        if (reserveLog == null) {
            throw new RuntimeException("找不到预扣凭证 " + reserveToken + " 的记录");
        }

        String skuCode = reserveLog.getSkuCode();
        Long warehouseId = reserveLog.getWarehouseId();
        int quantity = Math.abs(reserveLog.getChangeQuantity());

        Stock stock = stockRepository.findBySkuCodeAndWarehouseId(skuCode, warehouseId);
        if (stock == null) {
            throw new RuntimeException("库存记录不存在");
        }

        if (stock.getReservedQuantity() < quantity) {
            throw new RuntimeException("预扣库存不足，无法取消");
        }

        // 取消：预扣减，库存不变（释放回可用）
        stock.setReservedQuantity(stock.getReservedQuantity() - quantity);
        stockRepository.updateById(stock);

        // 创建取消日志
        createStockLog(skuCode, warehouseId, 0, StockLog.Type.CANCEL.getCode(), orderId,
                String.format("取消预扣释放库存，凭证 %s", reserveToken));

        log.info("取消预扣成功: token={}, orderId={}, quantity={}",
                reserveToken, orderId, quantity);

        return stock;
    }

    private String generateReserveToken(Long orderId, String skuCode) {
        return "RSV_" + orderId + "_" + skuCode + "_" + System.currentTimeMillis();
    }

    // ==================== 发货出库 ====================

    @Override
    @Transactional
    public Stock shipStock(String skuCode, Long warehouseId, Integer quantity, Long orderId, String trackingNo) {
        if (quantity <= 0) {
            throw new IllegalArgumentException("出库数量必须为正数");
        }

        Stock stock = getOrCreateStock(skuCode, warehouseId);

        // 检查锁定库存是否足够
        if (stock.getLockedQuantity() < quantity) {
            throw new RuntimeException(String.format(
                    "商品 %s 锁定库存不足，当前锁定%d，需出库%d",
                    skuCode, stock.getLockedQuantity(), quantity));
        }

        // 扣减总库存和锁定库存
        stock.setQuantity(stock.getQuantity() - quantity);
        stock.setLockedQuantity(stock.getLockedQuantity() - quantity);
        stockRepository.updateById(stock);

        // 创建发货日志
        createStockLog(skuCode, warehouseId, -quantity, StockLog.Type.SHIP.getCode(), orderId,
                String.format("发货出库，订单ID %d，运单号 %s", orderId, trackingNo));

        log.info("发货出库成功: skuCode={}, warehouseId={}, quantity={}, orderId={}, trackingNo={}",
                skuCode, warehouseId, quantity, orderId, trackingNo);

        return stock;
    }

    // ==================== 数据一致性检查 ====================

    @Override
    public ConsistencyCheckResult checkAndFixStockConsistency() {
        log.info("开始库存数据一致性检查...");

        List<Stock> allStocks = stockRepository.selectList(null);
        int checked = 0;
        int fixed = 0;
        List<String> errors = new ArrayList<>();

        for (Stock stock : allStocks) {
            checked++;

            // 计算实际库存（基于库存日志）
            int actualQuantity = calculateActualQuantity(stock.getSkuCode(), stock.getWarehouseId());

            // 检查是否一致
            if (!stock.getQuantity().equals(actualQuantity)) {
                int diff = actualQuantity - stock.getQuantity();

                log.warn("库存数据不一致，已修复: skuCode={}, warehouseId={}, oldQuantity={}, actualQuantity={}, diff={}",
                        stock.getSkuCode(), stock.getWarehouseId(), stock.getQuantity(), actualQuantity, diff);

                // 修复库存数据
                stock.setQuantity(actualQuantity);
                stockRepository.updateById(stock);
                fixed++;

                errors.add(String.format("SKU %s 在仓库 %d 的库存已从 %d 修复为 %d",
                        stock.getSkuCode(), stock.getWarehouseId(), stock.getQuantity() - diff, actualQuantity));
            }
        }

        log.info("库存一致性检查完成: checked={}, fixed={}", checked, fixed);

        return new ConsistencyCheckResult(checked, fixed, errors);
    }

    @Override
    public Integer calculateActualQuantity(String skuCode, Long warehouseId) {
        // TODO: 需要从 stock_initial 表获取初始库存
        // 目前暂时返回0，后续需要关联查询
        Integer initialStock = 0;

        // 累加所有变动
        Integer totalChange = stockLogRepository.selectList(
                new QueryWrapper<StockLog>()
                        .eq("sku_code", skuCode)
                        .eq("warehouse_id", warehouseId))
                .stream()
                .mapToInt(StockLog::getChangeQuantity)
                .sum();

        return initialStock + totalChange;
    }

    // ==================== 辅助方法 ====================

    @Override
    public Stock getOrCreateStock(String skuCode, Long warehouseId) {
        Stock stock = stockRepository.findBySkuCodeAndWarehouseId(skuCode, warehouseId);
        if (stock == null) {
            // 创建新记录
            stock = Stock.builder()
                    .skuCode(skuCode)
                    .skuName("未知商品") // 后续可以通过SKU服务获取
                    .warehouseId(warehouseId)
                    .quantity(0)
                    .lockedQuantity(0)
                    .reservedQuantity(0)
                    .defectiveQuantity(0)
                    .warningThreshold(0)
                    .version(0)
                    .build();
            stockRepository.insert(stock);
            log.info("创建新库存记录: skuCode={}, warehouseId={}", skuCode, warehouseId);
        }
        return stock;
    }

    @Override
    public StockLog createStockLog(String skuCode, Long warehouseId, Integer changeQuantity,
                                   String type, Long orderId, String remark) {
        StockLog log = StockLog.builder()
                .skuCode(skuCode)
                .warehouseId(warehouseId)
                .changeQuantity(changeQuantity)
                .type(type)
                .orderId(orderId)
                .remark(remark)
                .build();
        stockLogRepository.insert(log);
        return log;
    }

    // ==================== DTO转换方法 ====================

    private StockListItemDTO toStockListItemDTO(Stock stock, Map<Long, String> warehouseNameMap) {
        return StockListItemDTO.builder()
                .id(stock.getId())
                .skuCode(stock.getSkuCode())
                .skuName(stock.getSkuName())
                .warehouseId(stock.getWarehouseId())
                .warehouseName(warehouseNameMap.get(stock.getWarehouseId()))
                .quantity(stock.getQuantity())
                .lockedQuantity(stock.getLockedQuantity())
                .availableQuantity(stock.getAvailableQuantity())
                .defectiveQuantity(stock.getDefectiveQuantity())
                .warningThreshold(stock.getWarningThreshold())
                .isLow(stock.isLowStock())
                .createdAt(stock.getCreatedAt())
                .updatedAt(stock.getUpdatedAt())
                .build();
    }

    private StockLogDTO toStockLogDTO(StockLog log, Map<Long, String> warehouseNameMap) {
        return StockLogDTO.builder()
                .id(log.getId())
                .skuCode(log.getSkuCode())
                .warehouseId(log.getWarehouseId())
                .warehouseName(warehouseNameMap.get(log.getWarehouseId()))
                .changeQuantity(log.getChangeQuantity())
                .type(log.getType())
                .typeLabel(log.getTypeLabel())
                .relatedNo(log.getRelatedNo())
                .orderId(log.getOrderId())
                .deliveryNo(log.getDeliveryNo())
                .remark(log.getRemark())
                .createdAt(log.getCreatedAt())
                .build();
    }

    private StockWarningDTO toStockWarningDTO(Stock stock, Map<Long, String> warehouseNameMap) {
        return StockWarningDTO.builder()
                .id(stock.getId())
                .skuCode(stock.getSkuCode())
                .skuName(stock.getSkuName())
                .warehouseId(stock.getWarehouseId())
                .warehouseName(warehouseNameMap.get(stock.getWarehouseId()))
                .quantity(stock.getQuantity())
                .lockedQuantity(stock.getLockedQuantity())
                .availableQuantity(stock.getAvailableQuantity())
                .warningThreshold(stock.getWarningThreshold())
                .deficit(stock.getDeficit())
                .createdAt(stock.getCreatedAt())
                .updatedAt(stock.getUpdatedAt())
                .build();
    }

    private Map<Long, String> getWarehouseNameMap(List<Long> warehouseIds) {
        if (warehouseIds.isEmpty()) {
            return Map.of();
        }
        return warehouseRepository.selectList(
                new QueryWrapper<Warehouse>()
                        .in("id", warehouseIds))
                .stream()
                .collect(Collectors.toMap(Warehouse::getId, Warehouse::getName, (a, b) -> a));
    }

    // ==================== 事件发布 ====================

    /**
     * 发布库存变更事件
     */
    private void publishStockChangedEvent(Stock stock, String changeType, Integer changeQuantity,
                                          Integer oldQuantity, Integer newQuantity) {
        try {
            StockChangedEvent event = new StockChangedEvent(
                    stock.getSkuCode(),
                    stock.getSkuName(),
                    stock.getWarehouseId(),
                    changeType,
                    changeQuantity,
                    oldQuantity,
                    newQuantity
            );
            eventPublisher.publishEvent(event);
            log.debug("发布库存变更事件: skuCode={}, warehouseId={}, changeType={}",
                    stock.getSkuCode(), stock.getWarehouseId(), changeType);
        } catch (Exception e) {
            // 事件发布失败不影响主流程，仅记录日志
            log.warn("发布库存变更事件失败: skuCode={}, error={}", stock.getSkuCode(), e.getMessage());
        }
    }
}
