/**
 * Session-scoped store for cross-section filter state (TZ §4.1.8 Table 10).
 * In-memory only — cleared on page reload. Projection functions implement
 * the exact field mappings from Table 10 when a user navigates between
 * Online-Board ↔ Schedule. Map filter is stored separately and is NEVER
 * projected from / to Board or Schedule (per TZ §4.1.1 ¶12).
 */

import { isInBoardWindow } from "@/shared/dateWindow.js";

export interface BoardFilterSnapshot {
  mode: "route" | "flight-number" | "departure" | "arrival";
  departure?: string;
  arrival?: string;
  flightNumber?: string;
  date: string;      // yyyyMMdd
  timeFrom: string;  // HHmm
  timeTo: string;    // HHmm
  searchExecuted: boolean;
}

export interface ScheduleFilterSnapshot {
  mode: "route";
  departure?: string;
  arrival?: string;
  dateFrom: string;  // yyyyMMdd
  dateTo: string;
  timeFrom: string;
  timeTo: string;
  onlyDirect: boolean;
  showReturn: boolean;
  returnDateFrom?: string;
  returnDateTo?: string;
  returnTimeFrom?: string;
  returnTimeTo?: string;
  searchExecuted: boolean;
}

export interface MapFilterSnapshot {
  departure: string | null;
  arrival: string | null;
  date: string | null;
  showInternal: boolean;
  showInternational: boolean;
  showTransfers: boolean;
}

// Module-level in-memory state
let board: BoardFilterSnapshot | null = null;
let schedule: ScheduleFilterSnapshot | null = null;
let map: MapFilterSnapshot | null = null;

export function setBoardFilter(s: BoardFilterSnapshot): void { board = s; }
export function getBoardFilter(): BoardFilterSnapshot | null { return board; }
export function setScheduleFilter(s: ScheduleFilterSnapshot): void { schedule = s; }
export function getScheduleFilter(): ScheduleFilterSnapshot | null { return schedule; }
export function setMapFilter(s: MapFilterSnapshot): void { map = s; }
export function getMapFilter(): MapFilterSnapshot | null { return map; }

export function resetCrossSectionStore(): void {
  board = null; schedule = null; map = null;
}

function currentWeekBounds(base: Date): { start: string; end: string } {
  const d = new Date(base);
  d.setHours(0, 0, 0, 0);
  const dow = (d.getDay() + 6) % 7; // 0 = Mon .. 6 = Sun
  d.setDate(d.getDate() - dow);
  const start = new Date(d);
  const end = new Date(d);
  end.setDate(end.getDate() + 6);
  const y = (x: Date) =>
    `${x.getFullYear()}${String(x.getMonth() + 1).padStart(2, "0")}${String(x.getDate()).padStart(2, "0")}`;
  return { start: y(start), end: y(end) };
}

function todayYyyymmdd(): string {
  const d = new Date();
  return `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, "0")}${String(d.getDate()).padStart(2, "0")}`;
}

/** TZ Table 10: Board → Schedule projection. Preserves cities + dateFrom=current-week. */
export function projectBoardToSchedule(b: BoardFilterSnapshot): ScheduleFilterSnapshot {
  const base = b.date && /^\d{8}$/.test(b.date)
    ? new Date(Number(b.date.slice(0, 4)), Number(b.date.slice(4, 6)) - 1, Number(b.date.slice(6, 8)))
    : new Date();
  const week = currentWeekBounds(base);
  return {
    mode: "route",
    ...(b.departure ? { departure: b.departure } : {}),
    ...(b.arrival ? { arrival: b.arrival } : {}),
    dateFrom: week.start,
    dateTo: week.end,
    timeFrom: "0000",
    timeTo: "2400",
    onlyDirect: false,
    showReturn: false,
    searchExecuted: false,
  };
}

/**
 * TZ Table 10: Schedule → Board projection. Preserves cities.
 * Date: use schedule's dateFrom if it falls within the Board window
 * ([-1, +14] days from today); otherwise clamp to today. This preserves
 * user intent when the schedule date is near-term but avoids showing a
 * date the Board cannot display.
 */
export function projectScheduleToBoard(s: ScheduleFilterSnapshot): BoardFilterSnapshot {
  const date = isInBoardWindow(s.dateFrom) ? s.dateFrom : todayYyyymmdd();
  return {
    mode: "route",
    ...(s.departure ? { departure: s.departure } : {}),
    ...(s.arrival ? { arrival: s.arrival } : {}),
    date,
    timeFrom: "0000",
    timeTo: "2400",
    searchExecuted: false,
  };
}
