/**
 * Canonical timezone list — one city per major UTC offset. Every timezone
 * dropdown in the app renders exactly this list, and the server enforces it
 * (CambiumServer/utilities/timezones.py). timezones.test.js parses the Python file and
 * asserts the two lists stay identical.
 */

export const TIMEZONES = [
  'Pacific/Honolulu',
  'America/Anchorage',
  'America/Los_Angeles',
  'America/Denver',
  'America/Chicago',
  'America/New_York',
  'America/Sao_Paulo',
  'UTC',
  'Europe/London',
  'Europe/Paris',
  'Europe/Athens',
  'Europe/Moscow',
  'Asia/Dubai',
  'Asia/Kolkata',
  'Asia/Bangkok',
  'Asia/Shanghai',
  'Asia/Tokyo',
  'Australia/Sydney',
  'Pacific/Auckland',
];

/** "America/Los_Angeles" -> "America/Los Angeles" (display only). */
export function timezoneLabel(zone) {
  return zone.replace(/_/g, ' ');
}

/** Minutes east of UTC for `zone` at `date`. Throws on unknown zones. */
function offsetMinutes(zone, date) {
  const parts = new Intl.DateTimeFormat('en-US', {
    timeZone: zone,
    timeZoneName: 'longOffset',
  }).formatToParts(date);
  const name = parts.find((p) => p.type === 'timeZoneName')?.value ?? 'GMT';
  const m = name.match(/GMT([+-])(\d{2}):(\d{2})/);
  if (!m) return 0; // bare "GMT" — UTC itself
  return (m[1] === '-' ? -1 : 1) * (Number(m[2]) * 60 + Number(m[3]));
}

/**
 * Map an arbitrary IANA zone to the closest TIMEZONES entry by UTC offset at
 * `date`. Exact list members pass through; ties break by list order; unknown
 * or empty input falls back to "UTC".
 */
export function nearestTimezone(zone, date = new Date()) {
  if (typeof zone !== 'string' || !zone) return 'UTC';
  if (TIMEZONES.includes(zone)) return zone;
  let target;
  try {
    target = offsetMinutes(zone, date);
  } catch {
    return 'UTC';
  }
  let best = 'UTC';
  let bestDiff = Infinity;
  for (const candidate of TIMEZONES) {
    const diff = Math.abs(offsetMinutes(candidate, date) - target);
    if (diff < bestDiff) {
      best = candidate;
      bestDiff = diff;
    }
  }
  return best;
}
