package com.aps.macroplanner.data;

/**
 * 库存规格 (InventorySpec) — 对应 Quintiq 中的 InventorySpecification
 *
 * <p>定义某个产品/库存点/周期的库存水平约束。
 * 支持两种模式:</p>
 * <ul>
 *   <li><b>绝对数量模式</b>: targetLevel/minLevel/maxLevel 直接指定库存数量</li>
 *   <li><b>安全库存天数模式</b>: targetInDays/minLevelInDays/maxLevelInDays 指定天数,
 *       约束的 RHS 由未来周期的 DemandFulfillment 动态计算</li>
 * </ul>
 */
public class InventorySpec {
    private final Product product;
    private final StockingPoint stockingPoint;
    private final Period period;

    // === 绝对数量模式 ===
    private final double targetLevel;
    private final double minLevel;
    private final double maxLevel;
    private final boolean hasTarget;
    private final boolean hasMinLevel;
    private final boolean hasMaxLevel;

    // === 安全库存天数模式 ===
    /** 目标库存天数 (如 5 天), 0 表示不使用天数模式 */
    private final double targetInDays;
    /** 最小库存天数 (如 3 天) */
    private final double minLevelInDays;
    /** 最大库存天数 (如 10 天) */
    private final double maxLevelInDays;
    private final boolean hasTargetInDays;
    private final boolean hasMinLevelInDays;
    private final boolean hasMaxLevelInDays;

    public InventorySpec(Product product, StockingPoint stockingPoint, Period period,
                         double targetLevel, double minLevel, double maxLevel,
                         boolean hasTarget, boolean hasMinLevel, boolean hasMaxLevel) {
        this(product, stockingPoint, period,
                targetLevel, minLevel, maxLevel, hasTarget, hasMinLevel, hasMaxLevel,
                0.0, 0.0, 0.0, false, false, false);
    }

    public InventorySpec(Product product, StockingPoint stockingPoint, Period period,
                         double targetLevel, double minLevel, double maxLevel,
                         boolean hasTarget, boolean hasMinLevel, boolean hasMaxLevel,
                         double targetInDays, double minLevelInDays, double maxLevelInDays,
                         boolean hasTargetInDays, boolean hasMinLevelInDays, boolean hasMaxLevelInDays) {
        this.product = product;
        this.stockingPoint = stockingPoint;
        this.period = period;
        this.targetLevel = targetLevel;
        this.minLevel = minLevel;
        this.maxLevel = maxLevel;
        this.hasTarget = hasTarget;
        this.hasMinLevel = hasMinLevel;
        this.hasMaxLevel = hasMaxLevel;
        this.targetInDays = targetInDays;
        this.minLevelInDays = minLevelInDays;
        this.maxLevelInDays = maxLevelInDays;
        this.hasTargetInDays = hasTargetInDays;
        this.hasMinLevelInDays = hasMinLevelInDays;
        this.hasMaxLevelInDays = hasMaxLevelInDays;
    }

    public Product getProduct() { return product; }
    public StockingPoint getStockingPoint() { return stockingPoint; }
    public Period getPeriod() { return period; }
    public double getTargetLevel() { return targetLevel; }
    public double getMinLevel() { return minLevel; }
    public double getMaxLevel() { return maxLevel; }
    public boolean hasTarget() { return hasTarget; }
    public boolean hasMinLevel() { return hasMinLevel; }
    public boolean hasMaxLevel() { return hasMaxLevel; }

    public double getTargetInDays() { return targetInDays; }
    public double getMinLevelInDays() { return minLevelInDays; }
    public double getMaxLevelInDays() { return maxLevelInDays; }
    public boolean hasTargetInDays() { return hasTargetInDays; }
    public boolean hasMinLevelInDays() { return hasMinLevelInDays; }
    public boolean hasMaxLevelInDays() { return hasMaxLevelInDays; }

    public String getKey() {
        return product.getId() + "_" + stockingPoint.getId() + "_" + period.getIndex();
    }

    @Override
    public String toString() {
        return "InvSpec[" + product + ", " + stockingPoint + ", " + period + "]";
    }
}