package com.aps.macroplanner.constraint;

import com.google.ortools.linearsolver.MPConstraint;
import com.google.ortools.linearsolver.MPSolver;
import com.google.ortools.linearsolver.MPVariable;
import com.aps.macroplanner.data.*;
import com.aps.macroplanner.model.MacroPlannerModel;

import java.util.Map;

/**
 * 批次大小约束构建器 (LotSizeConstraint)
 *
 * <p>确保每个操作的生产量符合批次大小要求。</p>
 *
 * <h3>数学公式 (简化版, PTNrOfLots=1)</h3>
 * <pre>
 * 批次下限: PTQty × QTPFactor + PTLotSizeOver ≥ LotSize
 * 批次上限: PTQty × QTPFactor - PTLotSizeUnder ≤ LotSize
 * </pre>
 */
public class LotSizeConstraint {

    /**
     * 构建批次大小约束。
     */
    public static void build(MacroPlannerModel model, TestDataBuilder data) {
        Map<String, MPVariable> ptQtyVars = model.getPtQtyVars();
        Map<String, MPVariable> overVars = model.getPtLotSizeOverVars();
        Map<String, MPVariable> underVars = model.getPtLotSizeUnderVars();

        for (Operation op : data.getOperations()) {
            for (UnitOperation uo : op.getUnitOperations()) {
                if (!uo.hasLotSize()) continue;
                for (Period p : data.getPeriods()) {
                    String key = op.ptQtyKey(uo, p.getIndex());
                    MPVariable ptVar = ptQtyVars.get(key);
                    if (ptVar == null) continue;

                    double lotSize = uo.getLotSize();

                    // 批次下限
                    MPVariable ov = overVars.get(key);
                    if (ov != null) {
                        MPConstraint c = model.getSolver().makeConstraint(
                                lotSize, MPSolver.infinity(), "LotOver_" + key);
                        c.setCoefficient(ptVar, uo.getQtpfactor());
                        c.setCoefficient(ov, 1.0);
                    }

                    // 批次上限
                    MPVariable uv = underVars.get(key);
                    if (uv != null) {
                        MPConstraint c = model.getSolver().makeConstraint(
                                -MPSolver.infinity(), lotSize, "LotUnder_" + key);
                        c.setCoefficient(ptVar, uo.getQtpfactor());
                        c.setCoefficient(uv, -1.0);
                    }
                }
            }
        }
    }
}