// Curated list of common IANA timezones with widely recognised abbreviations.
// `code` is the abbreviation users expect to see (CET, ET, JST...). The IANA
// name (`zone`) is what we actually persist and pass to Intl APIs.
export interface TimezoneOption {
    zone: string;        // IANA name, e.g. "Europe/Berlin"
    code: string;        // colloquial abbreviation, e.g. "CET"
    label: string;       // human-friendly city/region name
}

export const TIMEZONE_OPTIONS: TimezoneOption[] = [
    { zone: "Pacific/Midway",        code: "SST",   label: "Samoa" },
    { zone: "Pacific/Honolulu",      code: "HST",   label: "Hawaii" },
    { zone: "America/Anchorage",     code: "AKT",   label: "Alaska" },
    { zone: "America/Los_Angeles",   code: "PT",    label: "Los Angeles, San Francisco" },
    { zone: "America/Denver",        code: "MT",    label: "Denver, Phoenix" },
    { zone: "America/Chicago",       code: "CT",    label: "Chicago, Mexico City" },
    { zone: "America/New_York",      code: "ET",    label: "New York, Toronto" },
    { zone: "America/Halifax",       code: "AT",    label: "Halifax" },
    { zone: "America/Sao_Paulo",     code: "BRT",   label: "São Paulo" },
    { zone: "America/Argentina/Buenos_Aires", code: "ART", label: "Buenos Aires" },
    { zone: "Atlantic/Azores",       code: "AZOT",  label: "Azores" },
    { zone: "Europe/London",         code: "GMT",   label: "London, Dublin, Lisbon" },
    { zone: "Europe/Berlin",         code: "CET",   label: "Berlin, Paris, Madrid, Rome" },
    { zone: "Europe/Athens",         code: "EET",   label: "Athens, Helsinki, Bucharest" },
    { zone: "Europe/Moscow",         code: "MSK",   label: "Moscow, Istanbul" },
    { zone: "Asia/Dubai",            code: "GST",   label: "Dubai, Abu Dhabi" },
    { zone: "Asia/Karachi",          code: "PKT",   label: "Karachi, Tashkent" },
    { zone: "Asia/Kolkata",          code: "IST",   label: "Mumbai, Delhi, Bengaluru" },
    { zone: "Asia/Dhaka",            code: "BST",   label: "Dhaka" },
    { zone: "Asia/Bangkok",          code: "ICT",   label: "Bangkok, Jakarta" },
    { zone: "Asia/Singapore",        code: "SGT",   label: "Singapore, Kuala Lumpur" },
    { zone: "Asia/Shanghai",         code: "CST",   label: "Beijing, Shanghai, Hong Kong" },
    { zone: "Asia/Tokyo",            code: "JST",   label: "Tokyo, Seoul" },
    { zone: "Australia/Perth",       code: "AWST",  label: "Perth" },
    { zone: "Australia/Adelaide",    code: "ACT",   label: "Adelaide" },
    { zone: "Australia/Sydney",      code: "AEST",  label: "Sydney, Melbourne" },
    { zone: "Pacific/Auckland",      code: "NZT",   label: "Auckland" },
    { zone: "UTC",                   code: "UTC",   label: "Coordinated Universal Time" },
];

// Compute the current offset (minutes) for an IANA zone using Intl.
// Positive means ahead of UTC.
export function getOffsetMinutes(zone: string, at: Date = new Date()): number {
    try {
        const dtf = new Intl.DateTimeFormat("en-US", {
            timeZone: zone,
            timeZoneName: "shortOffset",
        });
        const parts = dtf.formatToParts(at);
        const tzPart = parts.find((p) => p.type === "timeZoneName")?.value || "";
        // shortOffset returns like "GMT+01:00" or "GMT-5". Parse accordingly.
        const m = tzPart.match(/GMT([+-])(\d{1,2})(?::?(\d{2}))?/);
        if (!m) return 0;
        const sign = m[1] === "-" ? -1 : 1;
        const hours = parseInt(m[2] || "0", 10);
        const mins = parseInt(m[3] || "0", 10);
        return sign * (hours * 60 + mins);
    } catch {
        return 0;
    }
}

// Format minutes-offset as "+02:00" / "-05:30".
export function formatOffset(minutes: number): string {
    const sign = minutes >= 0 ? "+" : "-";
    const abs = Math.abs(minutes);
    const h = Math.floor(abs / 60).toString().padStart(2, "0");
    const m = (abs % 60).toString().padStart(2, "0");
    return `${sign}${h}:${m}`;
}

// Build a one-line label like "(UTC+01:00) CET — Berlin, Paris, …".
export function formatTimezone(opt: TimezoneOption, at: Date = new Date()): string {
    const off = formatOffset(getOffsetMinutes(opt.zone, at));
    return `(UTC${off}) ${opt.code} — ${opt.label}`;
}

// Get current time in a zone formatted as "HH:mm" (24h) or "h:mm a" (12h).
export function formatTimeInZone(zone: string, format: "12h" | "24h" = "24h", at: Date = new Date()): string {
    return new Intl.DateTimeFormat("en-GB", {
        timeZone: zone,
        hour: "2-digit",
        minute: "2-digit",
        hour12: format === "12h",
    }).format(at);
}

// Sort by offset asc, then by code/IANA name. Returns a fresh array.
export function sortedTimezones(at: Date = new Date()): TimezoneOption[] {
    return [...TIMEZONE_OPTIONS].sort((a, b) => {
        const oa = getOffsetMinutes(a.zone, at);
        const ob = getOffsetMinutes(b.zone, at);
        if (oa !== ob) return oa - ob;
        if (a.code !== b.code) return a.code.localeCompare(b.code);
        return a.zone.localeCompare(b.zone);
    });
}
