package jnpf.attendance.schedule;

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

/**
 * 按营业额与星期规则筛选出的「排班模板」参考历史日结果。
 */
public final class ScheduleTemplateSimilarDaysResult implements Serializable {

    public static final String MSG_NO_REFERENCE_DATA = "无参考数据，无法智能排班。";

    /**
     * 「规律模式」分支 (2)：目标日前连续自然日窗口长度（与 {@link SchedulePatternSimilarDaysAlgorithm} 一致）。
     */
    public static final int PATTERN_SCHEDULE_LAST_NATURAL_DAY_WINDOW = 7;

    /**
     * 规律模式兜底失败提示：{@code n = PATTERN_SCHEDULE_LAST_NATURAL_DAY_WINDOW - effectiveDaysWithShiftInLastWindow}，
     * 即「请先手动补满」的天数口径。
     */
    public static String msgInsufficientHistoryForPatternSchedule(int effectiveDaysWithShiftInLastWindow) {
        int clipped = Math.max(0, effectiveDaysWithShiftInLastWindow);
        int capped = Math.min(PATTERN_SCHEDULE_LAST_NATURAL_DAY_WINDOW, clipped);
        int needMoreNaturalDays = PATTERN_SCHEDULE_LAST_NATURAL_DAY_WINDOW - capped;
        return String.format(
                "提示：当前无历史排班信息，AI无参考数据。请先手动排班至少 %d 天后，再使用智能排班功能。",
                needMoreNaturalDays);
    }

    /** 识别 {@link #msgInsufficientHistoryForPatternSchedule(int)} 产出的文案（用于不完整说明聚合）。 */
    public static boolean isInsufficientHistoryForPatternScheduleMessage(String message) {
        return message != null && message.startsWith("提示：当前无历史排班信息，AI无参考数据。");
    }

    public enum SelectionTier {
        /** 同星期几 + 营业额 ±10%，样本 ≥10 */
        SAME_WEEKDAY_STRICT_BAND,
        /** 同星期几 + 营业额 ±15% */
        SAME_WEEKDAY_RELAXED_BAND,
        /** 同工作日/周末类型 + 营业额 ±15% */
        SAME_WORKDAY_TYPE_RELAXED_BAND,
        /** 营业额最接近 Top n */
        TOP_NEAREST_REVENUE,
        /** 无数据分析营业额：近 30 自然日内「同星期 + 有效班次列表」的全部参考日 */
        PATTERN_SAME_WEEKDAY_30D,
        /** 无数据分析营业额：目标日前连续 7 个自然日均须有效班次，采用这 7 日内全部参考日 */
        PATTERN_LAST_7_NATURAL_GE7,
        /** 未选到 */
        NONE
    }

    private final boolean success;
    private final List<LocalDate> similarDates;
    private final SelectionTier tier;
    private final String message;

    public ScheduleTemplateSimilarDaysResult(
            boolean success, List<LocalDate> similarDates, SelectionTier tier, String message) {
        this.success = success;
        this.similarDates =
                similarDates == null ? Collections.emptyList() : Collections.unmodifiableList(similarDates);
        this.tier = tier == null ? SelectionTier.NONE : tier;
        this.message = message == null ? "" : message;
    }

    public static ScheduleTemplateSimilarDaysResult failure(String message) {
        return new ScheduleTemplateSimilarDaysResult(false, Collections.emptyList(), SelectionTier.NONE, message);
    }

    public static ScheduleTemplateSimilarDaysResult ok(List<LocalDate> dates, SelectionTier tier) {
        return new ScheduleTemplateSimilarDaysResult(true, dates, tier, "");
    }

    public boolean isSuccess() {
        return success;
    }

    public List<LocalDate> getSimilarDates() {
        return similarDates;
    }

    public SelectionTier getTier() {
        return tier;
    }

    public String getMessage() {
        return message;
    }

    @Override
    public String toString() {
        return "ScheduleTemplateSimilarDaysResult{"
                + "success=" + success
                + ", tier=" + tier
                + ", count=" + similarDates.size()
                + ", message='" + message + '\''
                + '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        ScheduleTemplateSimilarDaysResult that = (ScheduleTemplateSimilarDaysResult) o;
        return success == that.success
                && tier == that.tier
                && Objects.equals(similarDates, that.similarDates)
                && Objects.equals(message, that.message);
    }

    @Override
    public int hashCode() {
        return Objects.hash(success, similarDates, tier, message);
    }
}
