package jnpf.attendance.schedule;

import java.time.LocalTime;

/**
 * 第六步：将班次起止时间统一到半小时粒度（与需求文档示例一致的「最近半小时」取整）。
 */
public final class ShiftHalfHourNormalizer {

    private ShiftHalfHourNormalizer() {}

    /** 将分钟数（0～1440+）就近取整到半小时刻度（0,30,60,…）。 */
    public static int roundMinuteToNearestHalfHour(int minuteOfDay) {
        long m = minuteOfDay;
        int q = (int) Math.round(m / 30.0);
        if (q < 0) {
            q = 0;
        }
        if (q > 48) {
            q = 48;
        }
        return q * 30;
    }

    /**
     * 对「左闭右开」区间 [start, end) 做半小时取整；若取整后无效（时长为 0），返回 {@code null}。
     * <p>
     * <b>仅限</b>已保证<strong>同日</strong>且 {@code end.isAfter(start)} 的片段。历史夜班（同日字段上
     * {@code end}≤{@code start}）不得在拆段<strong>之前</strong>传入：请先用与
     * {@link CommonFixedShiftDiscovery#splitToSameDayMinuteFragments(LocalDate, jnpf.model.attendance.vo.ShiftPostStatVo)}
     * 等价的方式拆成「当日尾」「次日首」两段再归一。（产品口径：不要求独立的「次日」字段；拆分在链路内自动完成。）
     */
    public static int[] normalizeSameDayStartEndExclusiveMinutes(LocalTime start, LocalTime end) {
        if (start == null || end == null || !end.isAfter(start)) {
            return null;
        }
        return normalizeMinuteRange(
                HalfHourSlotLabel.localTimeToMinute(start), HalfHourSlotLabel.localTimeToMinute(end));
    }

    /**
     * 对「左闭右开」分钟区间 [startMin, endMin) 做半小时取整；若无效返回 {@code null}。
     */
    public static int[] normalizeMinuteRange(int startMinuteInclusive, int endMinuteExclusive) {
        int sm = roundMinuteToNearestHalfHour(startMinuteInclusive);
        int em = roundMinuteToNearestHalfHour(endMinuteExclusive);
        if (em <= sm) {
            em = sm + 30;
        }
        if (em > 24 * 60) {
            em = 24 * 60;
        }
        if (em <= sm) {
            return null;
        }
        return new int[] {sm, em};
    }

    public static String toLabel(int startInclusiveMinute, int endExclusiveMinute) {
        return HalfHourSlotLabel.formatMinuteRange(startInclusiveMinute, endExclusiveMinute);
    }
}
