package com.aps.macroplanner.output.dto;

import java.util.ArrayList;
import java.util.List;

/**
 * 库存点库存结果 — 对应 Quintiq 中 ProductInStockingPointInPeriod (PISPIP) 的回写数据。
 *
 * <p>每个产品在每个库存点每个周期的库存状态、流入流出、规格偏差。</p>
 */
public class PispipResult {

    private String productId;
    private String spId;
    private int periodIndex;
    private String periodStartDate;

    // ===== 库存状态 =====

    /** 期初库存 (第0周期=初始库存, 其后=上周期 InvQty) */
    private double openingInventory;
    /** 期末库存 (InvQty) */
    private double endingInventory;

    // ===== 库存规格偏差 =====

    /** 目标库存水平 (绝对数量) */
    private Double targetInventoryLevel;
    /** 目标库存天数 (安全库存天数模式) */
    private Double targetInventoryDays;
    /** 低于目标库存量 (InvQtyUnderTarget) */
    private double belowTarget;
    /** 最小库存水平 (绝对数量) */
    private Double minInventoryLevel;
    /** 最小库存天数 (安全库存天数模式) */
    private Double minInventoryDays;
    /** 低于最小库存量 (MinInvQtyUnder) */
    private double belowMin;
    /** 最大库存水平 */
    private Double maxInventoryLevel;
    /** 最大库存天数 */
    private Double maxInventoryDays;
    /** 超过最大库存量 (MaxInvQtyOver) */
    private double aboveMax;

    // ===== 流入 =====

    /** 到货量 (生产完成到货, 含 lead time 偏移) */
    private double productionArrived;
    /** 在途到货量 (InTransitSupply) */
    private double inTransitArrival;
    /** 总流入量 */
    private double totalInflow;

    // ===== 流出 =====

    /** 销售需求量 (外部需求) */
    private double salesDemandQty;
    /** 销售满足量 */
    private double salesFulfilledQty;
    /** BOM 依赖需求量 (被其他工序消耗) */
    private double dependentDemandQty;
    /** 总流出量 */
    private double totalOutflow;

    // ===== 需求满足 =====

    /** 需求满足量 (DemandFulfillment = SalesDemandQty + BOM消耗, 用于安全库存天数) */
    private double demandFulfillment;
    /** 需求松弛 (DemandSlack) */
    private double demandSlack;

    // ===== 库存变化详情 =====

    /** 生产中 (当前周期 PTQty, 将来到货) */
    private double productionInProgress;
    /** 每个工序的产出明细 */
    private final List<ProductionDetail> productionDetails = new ArrayList<>();

    // ==================== 内嵌类 ====================

    /** 工序产出明细 */
    public static class ProductionDetail {
        public String operationId;
        public String operationName;
        public String unitId;
        public double quantity;
        public int leadTimeDays;
        /** 该工序的 BOM 输入物料消耗 */
        public final List<BomConsumption> bomConsumptions = new ArrayList<>();
    }

    /** BOM 物料消耗 */
    public static class BomConsumption {
        public String inputProductId;
        public String inputSpId;
        public double factor;
        public double consumedQty;
    }

    // ==================== Getters / Setters ====================

    public String getProductId() { return productId; }
    public void setProductId(String v) { this.productId = v; }

    public String getSpId() { return spId; }
    public void setSpId(String v) { this.spId = v; }

    public int getPeriodIndex() { return periodIndex; }
    public void setPeriodIndex(int v) { this.periodIndex = v; }

    public String getPeriodStartDate() { return periodStartDate; }
    public void setPeriodStartDate(String v) { this.periodStartDate = v; }

    public double getOpeningInventory() { return openingInventory; }
    public void setOpeningInventory(double v) { this.openingInventory = v; }

    public double getEndingInventory() { return endingInventory; }
    public void setEndingInventory(double v) { this.endingInventory = v; }

    public Double getTargetInventoryLevel() { return targetInventoryLevel; }
    public void setTargetInventoryLevel(Double v) { this.targetInventoryLevel = v; }

    public Double getTargetInventoryDays() { return targetInventoryDays; }
    public void setTargetInventoryDays(Double v) { this.targetInventoryDays = v; }

    public double getBelowTarget() { return belowTarget; }
    public void setBelowTarget(double v) { this.belowTarget = v; }

    public Double getMinInventoryLevel() { return minInventoryLevel; }
    public void setMinInventoryLevel(Double v) { this.minInventoryLevel = v; }

    public Double getMinInventoryDays() { return minInventoryDays; }
    public void setMinInventoryDays(Double v) { this.minInventoryDays = v; }

    public double getBelowMin() { return belowMin; }
    public void setBelowMin(double v) { this.belowMin = v; }

    public Double getMaxInventoryLevel() { return maxInventoryLevel; }
    public void setMaxInventoryLevel(Double v) { this.maxInventoryLevel = v; }

    public Double getMaxInventoryDays() { return maxInventoryDays; }
    public void setMaxInventoryDays(Double v) { this.maxInventoryDays = v; }

    public double getAboveMax() { return aboveMax; }
    public void setAboveMax(double v) { this.aboveMax = v; }

    public double getProductionArrived() { return productionArrived; }
    public void setProductionArrived(double v) { this.productionArrived = v; }

    public double getInTransitArrival() { return inTransitArrival; }
    public void setInTransitArrival(double v) { this.inTransitArrival = v; }

    public double getTotalInflow() { return totalInflow; }
    public void setTotalInflow(double v) { this.totalInflow = v; }

    public double getSalesDemandQty() { return salesDemandQty; }
    public void setSalesDemandQty(double v) { this.salesDemandQty = v; }

    public double getSalesFulfilledQty() { return salesFulfilledQty; }
    public void setSalesFulfilledQty(double v) { this.salesFulfilledQty = v; }

    public double getDependentDemandQty() { return dependentDemandQty; }
    public void setDependentDemandQty(double v) { this.dependentDemandQty = v; }

    public double getTotalOutflow() { return totalOutflow; }
    public void setTotalOutflow(double v) { this.totalOutflow = v; }

    public double getDemandFulfillment() { return demandFulfillment; }
    public void setDemandFulfillment(double v) { this.demandFulfillment = v; }

    public double getDemandSlack() { return demandSlack; }
    public void setDemandSlack(double v) { this.demandSlack = v; }

    public double getProductionInProgress() { return productionInProgress; }
    public void setProductionInProgress(double v) { this.productionInProgress = v; }

    public List<ProductionDetail> getProductionDetails() { return productionDetails; }
}