package jnpf.attendance.schedule;

/**
 * 智能排班<strong>第九、十步</strong>规则判定的统一端口，由业务侧接入真实人事/考勤数据。
 * <p>
 * <b>第九步</b>：{@link #passesOperationalHardConstraints} — 运营硬约束（请假、借调、资格、班次冲突等），
 * 违反任一则不可排该时段/岗位。<br>
 * <b>第十步</b>：五个 {@code violates*} 方法 — 与 {@link jnpf.model.attendance.vo.scheduling.FixedSchedulingRuleVo}
 * 配合，由 {@link FixedSoftConstraintRelaxationPlanner} / {@link ShiftPlanFinalStaffAssigner} 按「必须/尽量」调用。
 * <p>
 * <b>实现</b>
 * <ul>
 *   <li>{@link StaffRuleEvaluationPortPermissive} — 全放行，骨架联调；</li>
 *   <li>{@link StaffRuleEvaluationPortUsingScheduleRulesAndWorkSituation} — 固定规则 + 员工工作状态 VO（生产默认）。</li>
 * </ul>
 */
public interface StaffRuleEvaluationPort {

    /**
     * 第九步：是否通过运营硬约束。
     * <p>
     * 预期聚合：未离职、未请假、未外出、未借调、时段可用、岗位资格、不与已有班次冲突等
     * （具体由实现类对接各业务服务）。当前 {@link StaffRuleEvaluationPortUsingScheduleRulesAndWorkSituation}
     * 仅校验 employeeId 非空。
     *
     * @return true 表示可进入第十步固定规则判断
     */
    boolean passesOperationalHardConstraints(String employeeId, StaffAssignmentContext context);

    /**
     * 第十步：单日工作小时数是否违反上限。
     * <p>
     * 语义：{@code existingSameDayScheduledWorkHours + proposedAssignmentWorkHours > cap}；
     * 是否启用、cap 值、必须/尽量由 {@link FixedSchedulingRuleVo} 与 {@link FixedSoftRuleKind#DAILY_WORK_HOURS} 决定。
     */
    boolean violatesDailyWorkHoursLimit(String employeeId, StaffAssignmentContext context);

    /**
     * 第十步：连续工作天数是否违反上限。
     * <p>
     * 通常结合 {@link SchedulePeriodWorkTracker} 更新后的 {@code UserWorkSituationVo.continuousDays}。
     */
    boolean violatesConsecutiveWorkDaysLimit(String employeeId, StaffAssignmentContext context);

    /**
     * 第十步：每周工作天数是否违反上限。
     * <p>
     * 通常结合 {@code UserWorkSituationVo.weekWorkDays}（每次新排入一个自然日时 +1）。
     */
    boolean violatesWeeklyWorkDaysLimit(String employeeId, StaffAssignmentContext context);

    /**
     * 第十步：每周工作小时数是否违反上限。
     * <p>
     * 语义：{@code weekWorkHours + proposedAssignmentWorkHours > cap}。
     */
    boolean violatesWeeklyWorkHoursLimit(String employeeId, StaffAssignmentContext context);

    /**
     * 第十步：与上一班次间隔是否短于最小休息要求。
     * <p>
     * {@link StaffAssignmentContext#getMinutesRestSincePriorShiftEnd()} 为 null 时实现应返回 false（不判违反）。
     */
    boolean violatesMinRestBetweenShifts(String employeeId, StaffAssignmentContext context);
}
