import { setupI18n, type I18n, type Messages } from "@lingui/core";
import { messages as enMessages } from "../../locales/en/messages.po";

export const SUPPORTED_LOCALES = ["en", "es", "de", "ja"] as const;
export type AppLocale = (typeof SUPPORTED_LOCALES)[number];
export const DEFAULT_LOCALE: AppLocale = "en";

// es is Mexican Spanish (translations + dayjs es-mx).
export const LOCALE_LABELS: Record<AppLocale, string> = {
  en: "English",
  es: "Español",
  de: "Deutsch",
  ja: "日本語",
};

// Adding a language: add it to SUPPORTED_LOCALES + LOCALE_LABELS, add the
// locale to lingui.config.ts, run `bunx lingui extract`, and translate the
// generated src/locales/<locale>/messages.po.
const catalogLoaders = import.meta.glob<{ messages: Messages }>(
  "/src/locales/*/messages.po"
);

const messageCache: Partial<Record<AppLocale, Messages>> = {
  [DEFAULT_LOCALE]: enMessages,
};

export function resolveLocale(candidate: string | null | undefined): AppLocale {
  if (!candidate) return DEFAULT_LOCALE;
  const base = candidate.toLowerCase().split("-")[0];
  return (SUPPORTED_LOCALES as readonly string[]).includes(base)
    ? (base as AppLocale)
    : DEFAULT_LOCALE;
}

export async function ensureMessages(locale: AppLocale): Promise<Messages> {
  const cached = messageCache[locale];
  if (cached) return cached;

  const loader = catalogLoaders[`/src/locales/${locale}/messages.po`];
  if (!loader) return messageCache[DEFAULT_LOCALE]!;

  const { messages } = await loader();
  messageCache[locale] = messages;
  return messages;
}

export function getCachedMessages(locale: AppLocale): Messages {
  return messageCache[locale] ?? messageCache[DEFAULT_LOCALE]!;
}

export function hasCachedMessages(locale: AppLocale): boolean {
  return messageCache[locale] !== undefined;
}

export function createI18n(locale: AppLocale): I18n {
  const i18n = setupI18n();
  i18n.load(locale, getCachedMessages(locale));
  i18n.activate(locale);
  return i18n;
}

export function parseAcceptLanguage(header: string | null): AppLocale {
  if (!header) return DEFAULT_LOCALE;
  for (const part of header.split(",")) {
    const tag = part.split(";")[0]?.trim();
    if (!tag) continue;
    const base = tag.toLowerCase().split("-")[0];
    if ((SUPPORTED_LOCALES as readonly string[]).includes(base)) {
      return base as AppLocale;
    }
  }
  return DEFAULT_LOCALE;
}
