package com.erp.inventory.service;

import com.erp.inventory.entity.Stock;
import com.erp.inventory.entity.StockWarningRecord;
import com.erp.inventory.entity.StockWarningRule;
import com.erp.inventory.entity.Warehouse;
import com.erp.inventory.repository.StockRepository;
import com.erp.inventory.repository.StockWarningRecordRepository;
import com.erp.inventory.repository.StockWarningRuleRepository;
import com.erp.inventory.repository.WarehouseRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 库存预警自动检查服务
 * 当库存发生变化时，自动检查是否触发预警规则
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StockWarningCheckService {

    private final StockRepository stockRepository;
    private final StockWarningRuleRepository warningRuleRepository;
    private final StockWarningRecordRepository warningRecordRepository;
    private final WarehouseRepository warehouseRepository;
    private final StockWarningRuleService warningRuleService;

    /**
     * 检查库存是否触发预警规则
     * 当入库、出库、调整等操作导致库存变化时调用此方法
     * 
     * @param skuCode SKU编码
     * @param skuName SKU名称
     * @param warehouseId 仓库ID
     */
    @Async
    @Transactional
    public void checkAndTriggerWarnings(String skuCode, String skuName, Long warehouseId) {
        try {
            log.info("检查库存预警: skuCode={}, warehouseId={}", skuCode, warehouseId);
            
            // 获取当前库存
            Stock stock = stockRepository.findBySkuCodeAndWarehouseId(skuCode, warehouseId);
            if (stock == null) {
                log.info("库存记录不存在，跳过预警检查: skuCode={}, warehouseId={}", skuCode, warehouseId);
                return;
            }

            // 获取仓库名称
            String warehouseName = warehouseRepository.findNameById(warehouseId);

            // 获取匹配的预警规则
            List<StockWarningRule> matchedRules = warningRuleService.getMatchedRules(skuCode, warehouseId);

            if (matchedRules.isEmpty()) {
                log.info("没有匹配的预警规则: skuCode={}, warehouseId={}", skuCode, warehouseId);
                return;
            }

            for (StockWarningRule rule : matchedRules) {
                try {
                    checkRuleAndCreateWarning(stock, skuName, warehouseName, rule);
                } catch (Exception e) {
                    log.error("检查预警规则失败: ruleId={}, skuCode={}, error={}",
                            rule.getId(), skuCode, e.getMessage(), e);
                }
            }
        } catch (Exception e) {
            log.error("库存预警检查失败: skuCode={}, warehouseId={}, error={}",
                    skuCode, warehouseId, e.getMessage(), e);
        }
    }

    private void checkRuleAndCreateWarning(Stock stock, String skuName, String warehouseName, StockWarningRule rule) {
        int currentQuantity = stock.getQuantity() != null ? stock.getQuantity() : 0;
        int availableQuantity = stock.getAvailableQuantity();
        boolean shouldWarn = false;
        String ruleType = rule.getRuleType();

        switch (ruleType) {
            case "low_stock" -> {
                // 低库存预警：可用库存 <= 预警阈值
                int threshold = rule.getWarningThreshold() != null ? rule.getWarningThreshold() :
                        (rule.getSafetyStockMin() != null ? rule.getSafetyStockMin() : 0);
                shouldWarn = availableQuantity <= threshold;
            }
            case "high_stock" -> {
                // 高库存预警：当前库存 >= 最高库存上限
                int maxThreshold = rule.getMaxStockThreshold() != null ? rule.getMaxStockThreshold() :
                        (rule.getSafetyStockMax() != null ? rule.getSafetyStockMax() : Integer.MAX_VALUE);
                shouldWarn = currentQuantity >= maxThreshold;
            }
            case "out_of_stock" -> {
                // 缺货预警：可用库存 <= 0
                shouldWarn = availableQuantity <= 0;
            }
            default -> log.warn("未知的规则类型: {}", ruleType);
        }

        if (shouldWarn) {
            log.info("触发预警规则: ruleId={}, ruleName={}, skuCode={}, currentQty={}, availableQty={}",
                    rule.getId(), rule.getRuleName(), stock.getSkuCode(), currentQuantity, availableQuantity);

            StockWarningRecord record = warningRuleService.createWarningRecord(
                    stock.getSkuCode(),
                    skuName != null ? skuName : stock.getSkuName(),
                    stock.getWarehouseId(),
                    warehouseName,
                    rule,
                    currentQuantity,
                    availableQuantity
            );

            if (record != null) {
                log.info("创建预警记录: recordId={}", record.getId());
            }
        } else {
            log.debug("未触发预警规则: ruleId={}, skuCode={}, currentQty={}, availableQty={}",
                    rule.getId(), stock.getSkuCode(), currentQuantity, availableQuantity);
        }
    }

    /**
     * 批量检查所有库存的预警
     * 用于定时任务全量检查
     */
    @Transactional
    public void checkAllStocksWarnings() {
        log.info("开始批量检查所有库存预警...");

        List<Stock> allStocks = stockRepository.selectList(null);
        int checked = 0;
        int warned = 0;

        for (Stock stock : allStocks) {
            try {
                // 获取匹配的预警规则
                List<StockWarningRule> matchedRules = warningRuleService.getMatchedRules(
                        stock.getSkuCode(), stock.getWarehouseId());

                if (!matchedRules.isEmpty()) {
                    String warehouseName = warehouseRepository.findNameById(stock.getWarehouseId());

                    for (StockWarningRule rule : matchedRules) {
                        checkRuleAndCreateWarning(stock, stock.getSkuName(), warehouseName, rule);
                        warned++;
                    }
                }
                checked++;
            } catch (Exception e) {
                log.error("检查库存预警失败: skuCode={}, warehouseId={}, error={}",
                        stock.getSkuCode(), stock.getWarehouseId(), e.getMessage());
            }
        }

        log.info("批量检查完成: 共检查{}个库存，触发{}次预警", checked, warned);
    }

    /**
     * 根据规则类型检查库存
     * 
     * @param ruleType 规则类型：low_stock、high_stock、out_of_stock
     */
    @Transactional
    public void checkStocksByRuleType(String ruleType) {
        log.info("按规则类型检查库存预警: ruleType={}", ruleType);

        List<StockWarningRule> rules = warningRuleRepository.findByRuleTypeAndEnabled(ruleType, 1);

        if (rules.isEmpty()) {
            log.info("没有找到启用的{}规则", ruleType);
            return;
        }

        for (StockWarningRule rule : rules) {
            try {
                List<Stock> stocks = stockRepository.selectList(null);
                String warehouseName = rule.getWarehouseId() != null ?
                        warehouseRepository.findNameById(rule.getWarehouseId()) : null;

                for (Stock stock : stocks) {
                    // 过滤仓库
                    if (rule.getWarehouseId() != null && !rule.getWarehouseId().equals(stock.getWarehouseId())) {
                        continue;
                    }

                    // 过滤SKU
                    if (rule.getSkuCode() != null && !rule.getSkuCode().equals(stock.getSkuCode())) {
                        continue;
                    }

                    checkRuleAndCreateWarning(stock, stock.getSkuName(), warehouseName, rule);
                }
            } catch (Exception e) {
                log.error("检查规则类型预警失败: ruleId={}, ruleType={}, error={}",
                        rule.getId(), ruleType, e.getMessage());
            }
        }

        log.info("规则类型检查完成: ruleType={}", ruleType);
    }
}
