package jnpf.attendance.schedule;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * 第八步：在连续「仍有缺口」的半小时段上，用划线班段兜底（受最短/最长/段数限制）。
 */
public final class LineShiftGapPlanner {

    private LineShiftGapPlanner() {}

    /**
     * @param remainingNeedPerSlot 与矩阵行同序；值 &gt; 0 表示该半小时仍缺人数
     */
    public static List<LineShiftPick> planForPost(
            HalfHourPostDemandMatrix matrix,
            String postId,
            int[] remainingNeedPerSlot,
            LineShiftCoverConfig cfg) {
        Objects.requireNonNull(matrix, "matrix");
        Objects.requireNonNull(cfg, "cfg");
        if (postId == null) {
            postId = "";
        }
        List<String> slots = matrix.getSlotRangeLabelsOrdered();
        int n = slots.size();
        int[] need = remainingNeedPerSlot == null ? new int[n] : remainingNeedPerSlot.clone();
        if (need.length != n) {
            throw new IllegalArgumentException("remainingNeedPerSlot length must match matrix slots");
        }

        int min = cfg.getMinHalfHourSlots();
        int max = cfg.getMaxHalfHourSlots();
        int maxSeg = cfg.getMaxLineSegmentsPerPostPerDay();

        List<LineShiftPick> picks = new ArrayList<>();
        int segments = 0;
        int i = 0;
        while (i < n && segments < maxSeg) {
            if (need[i] <= 0) {
                i++;
                continue;
            }
            int j = i;
            while (j < n && need[j] > 0) {
                j++;
            }
            int pos = i;
            while (pos < j && segments < maxSeg) {
                int rem = j - pos;
                if (rem < min) {
                    break;
                }
                int len = Math.min(max, rem);
                if (rem - len > 0 && rem - len < min) {
                    if (rem >= 2 * min) {
                        len = rem - min;
                    } else {
                        len = rem;
                    }
                }
                if (len < min) {
                    break;
                }
                picks.add(new LineShiftPick(postId, pos, pos + len));
                for (int k = pos; k < pos + len; k++) {
                    need[k] = Math.max(0, need[k] - 1);
                }
                pos += len;
                segments++;
            }
            i = j;
        }
        return Collections.unmodifiableList(picks);
    }
}
