/**
 * Centralized date-window constants and membership helpers per TZ §4.1.2.
 *
 * All date arguments are "yyyyMMdd" strings (TZ URL date format).
 * Bounds are inclusive on both ends. Day-level comparison (time zeroed).
 */

export const BOARD_WINDOW_DAYS_BACK = 1;
export const BOARD_WINDOW_DAYS_FORWARD = 14;
export const SCHEDULE_WINDOW_DAYS_BACK = 1;
export const SCHEDULE_WINDOW_DAYS_FORWARD = 330;
export const MAP_WINDOW_DAYS_BACK = 1;
export const MAP_WINDOW_MONTHS_FORWARD = 6;

function today(): Date {
  const d = new Date();
  d.setHours(0, 0, 0, 0);
  return d;
}

function addDays(base: Date, days: number): Date {
  const d = new Date(base);
  d.setDate(d.getDate() + days);
  return d;
}

function addMonths(base: Date, months: number): Date {
  const d = new Date(base);
  d.setMonth(d.getMonth() + months);
  return d;
}

function parseYyyymmdd(s: string): Date | null {
  if (!/^\d{8}$/.test(s)) return null;
  const y = Number(s.slice(0, 4));
  const m = Number(s.slice(4, 6));
  const d = Number(s.slice(6, 8));
  if (m < 1 || m > 12 || d < 1 || d > 31) return null;
  const dt = new Date(y, m - 1, d);
  if (dt.getFullYear() !== y || dt.getMonth() !== m - 1 || dt.getDate() !== d) return null;
  return dt;
}

function inRange(date: Date, min: Date, max: Date): boolean {
  return date.getTime() >= min.getTime() && date.getTime() <= max.getTime();
}

export function boardWindowBounds(): [Date, Date] {
  const base = today();
  return [addDays(base, -BOARD_WINDOW_DAYS_BACK), addDays(base, BOARD_WINDOW_DAYS_FORWARD)];
}

export function scheduleWindowBounds(): [Date, Date] {
  const base = today();
  return [addDays(base, -SCHEDULE_WINDOW_DAYS_BACK), addDays(base, SCHEDULE_WINDOW_DAYS_FORWARD)];
}

export function mapWindowBounds(): [Date, Date] {
  const base = today();
  return [addDays(base, -MAP_WINDOW_DAYS_BACK), addMonths(base, MAP_WINDOW_MONTHS_FORWARD)];
}

export function isInBoardWindow(yyyymmdd: string): boolean {
  const d = parseYyyymmdd(yyyymmdd);
  if (!d) return false;
  const [min, max] = boardWindowBounds();
  return inRange(d, min, max);
}

export function isInScheduleWindow(yyyymmdd: string): boolean {
  const d = parseYyyymmdd(yyyymmdd);
  if (!d) return false;
  const [min, max] = scheduleWindowBounds();
  return inRange(d, min, max);
}

export function isInMapWindow(yyyymmdd: string): boolean {
  const d = parseYyyymmdd(yyyymmdd);
  if (!d) return false;
  const [min, max] = mapWindowBounds();
  return inRange(d, min, max);
}
