package jnpf.attendance.schedule;

import java.io.Serializable;
import java.time.LocalDate;
import java.util.Objects;

/**
 * 单次「拟分配」的规则判定上下文，供第九、十步 {@link StaffRuleEvaluationPort} 使用。
 * <p>
 * 由 {@link ShiftPlanFinalStaffAssigner#buildContext} 按<strong>每位员工</strong>构造
 * （因日工时、休息间隔因人而异）；{@link ScheduleStaffAssignmentSteps910} 场景下可能多人共用同一 context。
 */
public final class StaffAssignmentContext implements Serializable {

    private final LocalDate scheduleDay;
    private final String postId;
    /** 与 {@link HalfHourPostDemandMatrix} 行标签一致；可为 null 表示按整日聚合判断 */
    private final String slotRangeLabel;
    private final String groupId;
    /**
     * 该员工在本排班日、本段班<strong>之前</strong>已排工时（小时）。
     * 来源：{@link SchedulePeriodWorkTracker#getSameDayScheduledHours}。
     */
    private final double existingSameDayScheduledWorkHours;
    /**
     * 本段 {@link ShiftPlanBlock} 的工时（小时），与 existing 相加后用于日工时上限判断。
     */
    private final double proposedAssignmentWorkHours;
    /**
     * 本段开始与上一段结束之间的间隔（分钟）。
     * {@code null} 表示无上一段或无法计算 → {@link StaffRuleEvaluationPort#violatesMinRestBetweenShifts} 不判违反。
     */
    private final Integer minutesRestSincePriorShiftEnd;

    /** 简化构造：无已排工时、无休息间隔（仅用于联调或 Steps910 单上下文场景）。 */
    public StaffAssignmentContext(LocalDate scheduleDay, String postId, String slotRangeLabel, String groupId) {
        this(scheduleDay, postId, slotRangeLabel, groupId, 0d, 0d, null);
    }

    public StaffAssignmentContext(
            LocalDate scheduleDay,
            String postId,
            String slotRangeLabel,
            String groupId,
            double existingSameDayScheduledWorkHours,
            double proposedAssignmentWorkHours,
            Integer minutesRestSincePriorShiftEnd) {
        this.scheduleDay = Objects.requireNonNull(scheduleDay, "scheduleDay");
        this.postId = postId == null ? "" : postId;
        this.slotRangeLabel = slotRangeLabel;
        this.groupId = groupId == null ? "" : groupId;
        this.existingSameDayScheduledWorkHours = Math.max(0d, existingSameDayScheduledWorkHours);
        this.proposedAssignmentWorkHours = Math.max(0d, proposedAssignmentWorkHours);
        this.minutesRestSincePriorShiftEnd = minutesRestSincePriorShiftEnd;
    }

    public LocalDate getScheduleDay() {
        return scheduleDay;
    }

    public String getPostId() {
        return postId;
    }

    public String getSlotRangeLabel() {
        return slotRangeLabel;
    }

    public String getGroupId() {
        return groupId;
    }

    public double getExistingSameDayScheduledWorkHours() {
        return existingSameDayScheduledWorkHours;
    }

    public double getProposedAssignmentWorkHours() {
        return proposedAssignmentWorkHours;
    }

    public Integer getMinutesRestSincePriorShiftEnd() {
        return minutesRestSincePriorShiftEnd;
    }
}
