/**
 * Daylight-cycle timezone picker.
 *
 * Exposes:
 *   - `getTimezoneItems()` — IconSelectItem[] for the EntityPalette / EntitySelect
 *   - `enhanceTimezoneSelect(target, value, onChange?)` — replace a `<select>` with
 *     a refined EntitySelect picker. Idempotent; safe to call on every modal open.
 *   - `populateTimezoneSelect(id, value)` — back-compat for legacy callers that
 *     still want a plain native `<select>`.
 *
 * Each entry exposes a friendly city name and the timezone's *current* UTC
 * offset (computed via `Intl.DateTimeFormat`), so users see `Berlin · UTC+02:00`
 * instead of bare IANA strings like `Europe/Berlin`.
 */

import { t } from './i18n.ts';
import {
    ICON_GLOBE,
    ICON_SPARKLES,
    ICON_TARGET_ICON,
    ICON_CLOCK,
} from './icons.ts';
import type { IconSelectItem } from './icon-select.ts';
import { EntitySelect } from './entity-palette.ts';

type RegionKey =
    | 'utc'
    | 'europe'
    | 'africa'
    | 'me'
    | 'asia'
    | 'pacific'
    | 'americas';

interface TimezoneEntry {
    iana: string;
    region: RegionKey;
    city: string;
}

const TIMEZONES: ReadonlyArray<TimezoneEntry> = [
    { iana: 'UTC', region: 'utc', city: 'UTC' },

    // Europe
    { iana: 'Europe/London',    region: 'europe', city: 'London' },
    { iana: 'Europe/Lisbon',    region: 'europe', city: 'Lisbon' },
    { iana: 'Europe/Paris',     region: 'europe', city: 'Paris' },
    { iana: 'Europe/Berlin',    region: 'europe', city: 'Berlin' },
    { iana: 'Europe/Warsaw',    region: 'europe', city: 'Warsaw' },
    { iana: 'Europe/Helsinki',  region: 'europe', city: 'Helsinki' },
    { iana: 'Europe/Athens',    region: 'europe', city: 'Athens' },
    { iana: 'Europe/Moscow',    region: 'europe', city: 'Moscow' },
    { iana: 'Europe/Istanbul',  region: 'europe', city: 'Istanbul' },

    // Africa & Middle East
    { iana: 'Africa/Cairo',         region: 'africa', city: 'Cairo' },
    { iana: 'Africa/Lagos',         region: 'africa', city: 'Lagos' },
    { iana: 'Africa/Johannesburg',  region: 'africa', city: 'Johannesburg' },
    { iana: 'Asia/Dubai',           region: 'me',     city: 'Dubai' },
    { iana: 'Asia/Tehran',          region: 'me',     city: 'Tehran' },

    // Asia
    { iana: 'Asia/Karachi',     region: 'asia', city: 'Karachi' },
    { iana: 'Asia/Kolkata',     region: 'asia', city: 'Kolkata' },
    { iana: 'Asia/Bangkok',     region: 'asia', city: 'Bangkok' },
    { iana: 'Asia/Jakarta',     region: 'asia', city: 'Jakarta' },
    { iana: 'Asia/Singapore',   region: 'asia', city: 'Singapore' },
    { iana: 'Asia/Hong_Kong',   region: 'asia', city: 'Hong Kong' },
    { iana: 'Asia/Shanghai',    region: 'asia', city: 'Shanghai' },
    { iana: 'Asia/Seoul',       region: 'asia', city: 'Seoul' },
    { iana: 'Asia/Tokyo',       region: 'asia', city: 'Tokyo' },

    // Pacific
    { iana: 'Australia/Perth',      region: 'pacific', city: 'Perth' },
    { iana: 'Australia/Adelaide',   region: 'pacific', city: 'Adelaide' },
    { iana: 'Australia/Sydney',     region: 'pacific', city: 'Sydney' },
    { iana: 'Pacific/Auckland',     region: 'pacific', city: 'Auckland' },
    { iana: 'Pacific/Honolulu',     region: 'pacific', city: 'Honolulu' },

    // Americas
    { iana: 'America/Anchorage',                region: 'americas', city: 'Anchorage' },
    { iana: 'America/Los_Angeles',              region: 'americas', city: 'Los Angeles' },
    { iana: 'America/Denver',                   region: 'americas', city: 'Denver' },
    { iana: 'America/Chicago',                  region: 'americas', city: 'Chicago' },
    { iana: 'America/Mexico_City',              region: 'americas', city: 'Mexico City' },
    { iana: 'America/New_York',                 region: 'americas', city: 'New York' },
    { iana: 'America/Toronto',                  region: 'americas', city: 'Toronto' },
    { iana: 'America/Sao_Paulo',                region: 'americas', city: 'São Paulo' },
    { iana: 'America/Argentina/Buenos_Aires',   region: 'americas', city: 'Buenos Aires' },
];

const REGION_FALLBACK: Record<RegionKey, string> = {
    utc:      'UTC',
    europe:   'Europe',
    africa:   'Africa',
    me:       'Middle East',
    asia:     'Asia',
    pacific:  'Pacific',
    americas: 'Americas',
};

function _detectedTimezone(): string {
    try {
        return Intl.DateTimeFormat().resolvedOptions().timeZone || '';
    } catch {
        return '';
    }
}

/** Compute the current UTC offset for a given IANA zone, formatted as `UTC+02:00`. */
function _utcOffsetLabel(iana: string): string {
    try {
        const fmt = new Intl.DateTimeFormat('en-US', {
            timeZone: iana,
            timeZoneName: 'longOffset',
        });
        const parts = fmt.formatToParts(new Date());
        const raw = parts.find(p => p.type === 'timeZoneName')?.value || '';
        // Intl returns 'GMT+02:00' for offsets and 'GMT' for UTC. Normalize.
        if (raw === 'GMT' || raw === '') return 'UTC';
        return raw.replace(/^GMT/, 'UTC');
    } catch {
        return '';
    }
}

function _friendlyCityFromIana(iana: string): string {
    const last = iana.split('/').pop() || iana;
    return last.replace(/_/g, ' ');
}

function _regionLabel(region: RegionKey): string {
    return t(`common.daylight_tz.region.${region}`) || REGION_FALLBACK[region];
}

function _formatRowLabel(city: string, offset: string): string {
    // Em-dash separator, monospaced offset rendered via CSS on the popup.
    return offset ? `${city} · ${offset}` : city;
}

/** Build the list of items for an EntitySelect timezone picker. */
export function getTimezoneItems(): IconSelectItem[] {
    const items: IconSelectItem[] = [];
    const detected = _detectedTimezone();

    items.push({
        value: '',
        icon: ICON_TARGET_ICON,
        label: t('common.daylight_tz.system') || 'System default',
        desc: t('common.daylight_tz.system_desc') || 'Server clock',
    });

    if (detected) {
        const offset = _utcOffsetLabel(detected);
        const city = _friendlyCityFromIana(detected);
        const detectedLabel = t('common.daylight_tz.detected_label') || 'Auto-detected';
        items.push({
            value: detected,
            icon: ICON_SPARKLES,
            label: _formatRowLabel(city, offset),
            desc: `${detectedLabel} · ${detected}`,
        });
    }

    for (const tz of TIMEZONES) {
        if (detected && tz.iana === detected) continue;
        const offset = _utcOffsetLabel(tz.iana);
        const region = _regionLabel(tz.region);
        items.push({
            value: tz.iana,
            icon: tz.region === 'utc' ? ICON_CLOCK : ICON_GLOBE,
            label: _formatRowLabel(tz.city, offset),
            desc: `${region} · ${tz.iana}`,
        });
    }
    return items;
}

/**
 * Populate a `<select>` with timezone options. Kept for back-compat; the new
 * preferred entrypoint is `enhanceTimezoneSelect()`.
 */
export function populateTimezoneSelect(selectId: string, currentValue: string): void {
    const select = document.getElementById(selectId) as HTMLSelectElement | null;
    if (!select) return;
    _syncNativeOptions(select, currentValue);
}

function _syncNativeOptions(select: HTMLSelectElement, currentValue: string): void {
    const items = getTimezoneItems();
    const seen = new Set<string>();
    const fragments: string[] = [];
    for (const item of items) {
        if (seen.has(item.value)) continue;
        seen.add(item.value);
        const text = item.desc ? `${item.label} — ${item.desc}` : item.label;
        fragments.push(`<option value="${_escapeAttr(item.value)}">${_escapeText(text)}</option>`);
    }
    if (currentValue && !seen.has(currentValue)) {
        fragments.unshift(
            `<option value="${_escapeAttr(currentValue)}">${_escapeText(currentValue)}</option>`,
        );
    }
    select.innerHTML = fragments.join('');
    select.value = currentValue || '';
}

function _escapeAttr(s: string): string {
    return s.replace(/[&<>"']/g, c =>
        c === '&' ? '&amp;'
        : c === '<' ? '&lt;'
        : c === '>' ? '&gt;'
        : c === '"' ? '&quot;'
        : '&#39;',
    );
}
function _escapeText(s: string): string {
    return _escapeAttr(s);
}

const _enhanced = new WeakMap<HTMLSelectElement, EntitySelect>();

/**
 * Replace a native `<select>` with the refined timezone EntitySelect picker.
 * Idempotent — calling on the same element again refreshes items and value.
 */
export function enhanceTimezoneSelect(
    target: HTMLSelectElement,
    currentValue: string,
    onChange?: (value: string) => void,
): EntitySelect {
    _syncNativeOptions(target, currentValue);

    const existing = _enhanced.get(target);
    if (existing) {
        existing.refresh();
        existing.setValue(currentValue || '');
        return existing;
    }

    const trigger = target.parentElement?.classList.contains('tz-picker-wrap');
    if (trigger) {
        // Hint for stylesheet: distinguish the timezone trigger from generic ones.
        target.parentElement!.dataset.tzPicker = '';
    }

    const es = new EntitySelect({
        target,
        getItems: getTimezoneItems,
        placeholder: t('common.daylight_tz.search') || 'Search timezones…',
        onChange,
    });
    _enhanced.set(target, es);
    return es;
}
