/**
 * Event start times in Brussels local wall time, converted to UTC the same way as
 * backend/src/api/calendar.ts (parseEventDates). Keeps admin/public UI aligned with ICS.
 */

// Parse "HH:MM", "H:MM am/pm", "Hpm" etc.
function parseLocalTime(t: string): { h: number; m: number } {
  const clean = t.trim();
  const m24 = clean.match(/^(\d{1,2}):(\d{2})$/);
  if (m24) return { h: parseInt(m24[1], 10), m: parseInt(m24[2], 10) };

  const mAp = clean.match(/^(\d{1,2})(?::(\d{2}))?\s*(am|pm)$/i);
  if (mAp) {
    let h = parseInt(mAp[1], 10);
    const m = mAp[2] ? parseInt(mAp[2], 10) : 0;
    if (mAp[3].toLowerCase() === "pm" && h !== 12) h += 12;
    if (mAp[3].toLowerCase() === "am" && h === 12) h = 0;
    return { h, m };
  }
  return { h: 18, m: 0 };
}

// Brussels is UTC+1 (CET) / UTC+2 (CEST). Same as calendar.ts.
const BRUSSELS_OFFSET_HOURS = 1;

/** Extract YYYY-MM-DD from stored date (ISO date-only or full ISO datetime). */
export function normalizeMeetupDateKey(dateStr: string): string | null {
  const s = dateStr?.trim();
  if (!s) return null;
  const dayPart = s.includes("T") ? s.split("T")[0]! : s.slice(0, 10);
  if (!/^\d{4}-\d{2}-\d{2}$/.test(dayPart)) return null;
  return dayPart;
}

/**
 * Returns event start instant in UTC, or Invalid Date if date/time cannot be parsed.
 */
export function getMeetupStartUtc(dateStr: string, timeStr: string): Date {
  const key = normalizeMeetupDateKey(dateStr);
  if (!key) return new Date(NaN);
  const parts = key.split("-").map(Number);
  const year = parts[0];
  const month = parts[1];
  const day = parts[2];
  if (!year || !month || !day) return new Date(NaN);

  const t = timeStr?.trim() ? timeStr : "00:00";
  const timeParts = t.split(/\s*[-–]\s*/);
  const { h: startH, m: startM } = parseLocalTime(timeParts[0] ?? "");

  const utcStartH = startH - BRUSSELS_OFFSET_HOURS;
  return new Date(Date.UTC(year, month - 1, day, utcStartH, startM, 0));
}

/**
 * Returns the event end instant in UTC when the time string carries a range
 * (e.g. "18:00 - 21:00"), otherwise null. Used for schema.org Event.endDate.
 */
export function getMeetupEndUtc(dateStr: string, timeStr: string): Date | null {
  const key = normalizeMeetupDateKey(dateStr);
  if (!key) return null;
  const parts = key.split("-").map(Number);
  const year = parts[0];
  const month = parts[1];
  const day = parts[2];
  if (!year || !month || !day) return null;

  const timeParts = (timeStr?.trim() || "").split(/\s*[-–]\s*/);
  if (timeParts.length < 2 || !timeParts[1]?.trim()) return null;

  const { h: endH, m: endM } = parseLocalTime(timeParts[1]);
  const utcEndH = endH - BRUSSELS_OFFSET_HOURS;
  return new Date(Date.UTC(year, month - 1, day, utcEndH, endM, 0));
}

const UTC_CAL_OPTS = { timeZone: "UTC" } as const;

/**
 * Format the stored meetup calendar date (YYYY-MM-DD) for display without shifting
 * by the viewer's timezone. Date-only strings parsed as new Date("YYYY-MM-DD") are
 * UTC midnight and show the wrong local day in western zones.
 */
export function formatMeetupCivilDate(dateStr: string): {
  monthShort: string;
  day: string;
  full: string;
} | null {
  const key = normalizeMeetupDateKey(dateStr);
  if (!key) return null;
  const parts = key.split("-").map(Number);
  const year = parts[0];
  const month = parts[1];
  const dayNum = parts[2];
  if (!year || !month || !dayNum) return null;

  const ref = new Date(Date.UTC(year, month - 1, dayNum, 12, 0, 0));
  return {
    monthShort: ref
      .toLocaleString("en-US", { ...UTC_CAL_OPTS, month: "short" })
      .toUpperCase(),
    day: String(ref.getUTCDate()),
    full: ref.toLocaleString("en-US", {
      ...UTC_CAL_OPTS,
      weekday: "long",
      year: "numeric",
      month: "long",
      day: "numeric",
    }),
  };
}

/** Long single-line civil date for event detail (same rules as formatMeetupCivilDate). */
export function formatMeetupCivilDateLong(dateStr: string): string {
  return formatMeetupCivilDate(dateStr)?.full ?? "—";
}
