/**
 * date-ist.ts — IST-aware date/time helpers.
 *
 * All functions explicitly pass timeZone: "Asia/Kolkata" so they produce
 * consistent IST output regardless of where they run — Next.js SSR on a
 * European server OR the user's browser.
 *
 * Never use new Date().toDateString(), .getHours(), or .toLocaleString()
 * without a timeZone option — those use the host's local timezone.
 */

const TZ = "Asia/Kolkata";
const LOCALE = "en-IN";

/**
 * Safely convert any timestamp to a Date, treating no-timezone strings as UTC.
 *
 * Why: `new Date("2024-05-28T09:00:00")` (no 'Z') is treated as *local* time by
 * browsers/Node, which breaks IST display when the host is in a different tz.
 * `new Date("2024-05-28T09:00:00.000Z")` is always UTC regardless of host tz.
 *
 * Our postgres.js custom parser already appends 'Z', so DB values are always safe.
 * This helper is a safety net for values from other sources (API responses, props).
 */
function toUTCDate(isoOrDate: string | Date): Date {
  if (isoOrDate instanceof Date) return isoOrDate;
  const s = isoOrDate as string;
  // Already has explicit timezone: trailing 'Z' or '+HH:MM' / '-HH:MM' offset
  if (s.endsWith("Z") || /[+-]\d{2}:\d{2}$/.test(s)) return new Date(s);
  // No timezone marker — assume UTC (postgres timestamp without time zone)
  return new Date(s + "Z");
}

/** ISO date string (YYYY-MM-DD) for today in IST — use for comparisons. */
export function todayIST(): string {
  // "sv-SE" locale gives YYYY-MM-DD — a clean, comparable format.
  return new Date().toLocaleDateString("sv-SE", { timeZone: TZ });
}

/** ISO date string (YYYY-MM-DD) for any timestamp, evaluated in IST. */
export function dateIST(isoOrDate: string | Date): string {
  return toUTCDate(isoOrDate).toLocaleDateString("sv-SE", { timeZone: TZ });
}

/** True if the given timestamp falls on today in IST. */
export function isTodayIST(isoOrDate: string | Date): boolean {
  return dateIST(isoOrDate) === todayIST();
}

/** ISO date string N calendar days before today in IST. */
function nDaysAgoIST(n: number): string {
  const d = new Date();
  d.setDate(d.getDate() - n);
  return d.toLocaleDateString("sv-SE", { timeZone: TZ });
}

/** Current hour 0-23 in IST. Replaces new Date().getHours() on the server. */
export function hourIST(): number {
  // Intl gives a locale-formatted hour string; parseInt handles "24" edge case.
  const str = new Intl.DateTimeFormat(LOCALE, {
    timeZone: TZ,
    hour: "numeric",
    hour12: false,
  }).format(new Date());
  const h = parseInt(str, 10);
  return h === 24 ? 0 : h;
}

/** Format a timestamp as "hh:mm AM/PM" in IST. */
export function fmtTime(isoOrDate: string | Date): string {
  return toUTCDate(isoOrDate).toLocaleTimeString(LOCALE, {
    timeZone: TZ,
    hour: "2-digit",
    minute: "2-digit",
  });
}

/** Format a timestamp as a date string in IST with given Intl options. */
export function fmtDate(
  isoOrDate: string | Date,
  opts: Intl.DateTimeFormatOptions = { day: "numeric", month: "short", year: "numeric" }
): string {
  return toUTCDate(isoOrDate).toLocaleDateString(LOCALE, { timeZone: TZ, ...opts });
}

/**
 * "Today" | "Yesterday" | "Mon, 26 May" — for activity group headers.
 * Replaces the toDateString()-based pattern throughout the app.
 */
export function dayLabel(isoOrDate: string | Date): string {
  const d = dateIST(isoOrDate);
  if (d === todayIST())       return "Today";
  if (d === nDaysAgoIST(1))   return "Yesterday";
  return fmtDate(isoOrDate, { weekday: "short", month: "short", day: "numeric" });
}

/**
 * Like dayLabel but short ("Today" | "Yest." | "Mon").
 * Used in the activity page bar chart labels.
 */
export function shortDayLabel(isoOrDate: string | Date, index: number): string {
  if (index === 0) return "Today";
  if (index === 1) return "Yest.";
  return fmtDate(isoOrDate, { weekday: "short" });
}
