import { planScheduleSlots, parseProjectTimezone } from "./plan-times";

const SLOT_WINDOW_MINUTES = 30;

export interface SlotCheckResult {
  allowed: boolean;
  reason: string;
  localTime: string;
  timezone: string;
  regions: string[];
  slots: ReturnType<typeof planScheduleSlots>;
}

function formatLocalTime(date: Date, timeZone: string): string {
  try {
    return new Intl.DateTimeFormat("en-US", {
      timeZone,
      hour: "numeric",
      minute: "2-digit",
      hour12: true,
      weekday: "short",
    }).format(date);
  } catch {
    return date.toISOString();
  }
}

function localParts(date: Date, timeZone: string): { hour: number; minute: number } {
  try {
    const parts = new Intl.DateTimeFormat("en-US", {
      timeZone,
      hour: "numeric",
      minute: "numeric",
      hourCycle: "h23",
    }).formatToParts(date);
    const hour = Number(parts.find((p) => p.type === "hour")?.value ?? 0);
    const minute = Number(parts.find((p) => p.type === "minute")?.value ?? 0);
    return { hour, minute };
  } catch {
    return { hour: date.getUTCHours(), minute: date.getUTCMinutes() };
  }
}

function minutesSinceMidnight(hour: number, minute: number) {
  return hour * 60 + minute;
}

export function getActiveScheduleSlots(input: {
  timezone: string;
  postsPerDay: 1 | 2;
  scheduleSeed: number;
  now?: Date;
}) {
  const timeZone = parseProjectTimezone(input.timezone);
  const now = input.now ?? new Date();
  const slots = planScheduleSlots(input.postsPerDay, input.scheduleSeed);
  const { hour, minute } = localParts(now, timeZone);
  const nowMins = minutesSinceMidnight(hour, minute);

  return slots.filter((slot) => {
    const slotMins = minutesSinceMidnight(slot.hour, slot.minute);
    return Math.abs(nowMins - slotMins) <= SLOT_WINDOW_MINUTES;
  });
}

export function checkScheduleSlot(input: {
  timezone: string;
  countries: string[];
  postsPerDay: 1 | 2;
  scheduleSeed: number;
  now?: Date;
}): SlotCheckResult {
  const timeZone = parseProjectTimezone(input.timezone);
  const now = input.now ?? new Date();
  const slots = planScheduleSlots(input.postsPerDay, input.scheduleSeed);
  const { hour, minute } = localParts(now, timeZone);
  const nowMins = minutesSinceMidnight(hour, minute);

  const inWindow = slots.some((slot) => {
    const slotMins = minutesSinceMidnight(slot.hour, slot.minute);
    return Math.abs(nowMins - slotMins) <= SLOT_WINDOW_MINUTES;
  });

  const slotList = slots.map((s) => s.display).join(", ");
  const regions = input.countries.length ? input.countries : ["not set"];
  const localTime = formatLocalTime(now, timeZone);

  if (inWindow) {
    return {
      allowed: true,
      reason: `Within schedule window (${slotList}) in ${timeZone}.`,
      localTime,
      timezone: timeZone,
      regions,
      slots,
    };
  }

  return {
    allowed: false,
    reason: `Outside schedule slots [${slotList}] for timezone ${timeZone} (now: ${localTime}). Target regions: ${regions.join(", ")}. Use manual publish to override.`,
    localTime,
    timezone: timeZone,
    regions,
    slots,
  };
}
