"use client";

import { useSession } from "@/lib/auth-client";

// Public-readable default (Next.js exposes NEXT_PUBLIC_* to the browser).
// Operators can set this in .env.local to match the server-side
// DEFAULT_TIMEZONE. If unset, both server and client default to 'UTC'.
function getClientDefaultTimezone(): string {
  return process.env.NEXT_PUBLIC_DEFAULT_TIMEZONE || "UTC";
}

function isValidIanaTimezone(tz: unknown): tz is string {
  if (typeof tz !== "string" || tz.length === 0 || tz.length > 64) return false;
  try {
    return Intl.supportedValuesOf("timeZone").includes(tz);
  } catch {
    return false;
  }
}

/**
 * useUserTimezone — TZ-04.
 *
 * Returns the calling user's IANA timezone string, sourced from the
 * Better Auth additionalField on `useSession()`. Falls back to
 * `process.env.NEXT_PUBLIC_DEFAULT_TIMEZONE || 'UTC'` while the session
 * is loading, when the field is missing, or when the stored value is
 * not a recognized IANA zone.
 *
 * This is the ONLY supported way to read the user's tz on the client.
 * Do NOT call `Intl.DateTimeFormat()` with a hardcoded zone or rely on
 * the browser's local zone — the user may have travelled or set a
 * preference that differs from the device.
 */
export function useUserTimezone(): string {
  const { data } = useSession();
  // Better Auth additionalField is typed `string` post-Plan-01; defence
  // in depth: validate before returning.
  const raw = (data?.user as { timezone?: unknown } | undefined)?.timezone;
  if (isValidIanaTimezone(raw)) return raw;
  return getClientDefaultTimezone();
}

/**
 * formatInUserTimezone — convenience wrapper for the common case of
 * "format an ISO string in the user's tz". Equivalent to
 * `new Date(iso).toLocaleString(locale, { ...options, timeZone: tz })`.
 *
 * Pass `tz` from `useUserTimezone()` and the same options object you'd
 * pass to toLocaleString / toLocaleDateString — this helper keeps
 * existing format strings working without rewrites.
 */
export function formatInUserTimezone(
  input: string | number | Date,
  tz: string,
  options?: Intl.DateTimeFormatOptions,
  locale: string = "en-US",
): string {
  const date = input instanceof Date ? input : new Date(input);
  return date.toLocaleString(locale, { ...options, timeZone: tz });
}
