import { messages } from './messages';

export const SUPPORTED_LOCALES = ['zh-CN', 'en'] as const;
export type Locale = (typeof SUPPORTED_LOCALES)[number];
export const DEFAULT_LOCALE: Locale = 'zh-CN';
export const LOCALE_COOKIE_NAME = 'termi_locale';

type TranslateParams = Record<string, string | number | null | undefined>;

function resolveMessage(locale: Locale, key: string): string | undefined {
  const segments = key.split('.');
  let current: unknown = messages[locale];

  for (const segment of segments) {
    if (!current || typeof current !== 'object' || !(segment in current)) {
      current = undefined;
      break;
    }
    current = (current as Record<string, unknown>)[segment];
  }

  return typeof current === 'string' ? current : undefined;
}

function interpolate(template: string, params?: TranslateParams): string {
  if (!params) {
    return template;
  }

  return template.replace(/\{(\w+)\}/g, (_, name) => String(params[name] ?? ''));
}

export function normalizeLocale(value: string | null | undefined): Locale | null {
  if (!value) {
    return null;
  }

  const normalized = value.trim().toLowerCase();
  if (!normalized) {
    return null;
  }

  if (normalized.startsWith('zh')) {
    return 'zh-CN';
  }

  if (normalized.startsWith('en')) {
    return 'en';
  }

  return null;
}

export function resolveLocale(options: {
  query?: string | null;
  cookie?: string | null;
  acceptLanguage?: string | null;
}): Locale {
  const fromQuery = normalizeLocale(options.query);
  if (fromQuery) {
    return fromQuery;
  }

  const fromCookie = normalizeLocale(options.cookie);
  if (fromCookie) {
    return fromCookie;
  }

  return DEFAULT_LOCALE;
}

export function translate(locale: Locale, key: string, params?: TranslateParams): string {
  const template =
    resolveMessage(locale, key) ??
    resolveMessage(DEFAULT_LOCALE, key) ??
    key;

  return interpolate(template, params);
}

export function getMessages(locale: Locale) {
  return messages[locale];
}

export function buildLocaleUrl(url: URL, locale: Locale): string {
  const next = new URL(url);
  next.searchParams.set('lang', locale);
  return `${next.pathname}${next.search}${next.hash}`;
}

export function getI18n(Astro: {
  url: URL;
  request: Request;
  cookies?: {
    get?: (name: string) => { value: string } | undefined;
  };
}) {
  const requestUrl = new URL(Astro.request.url);
  const locale = resolveLocale({
    query: requestUrl.searchParams.get('lang'),
    cookie: Astro.cookies?.get?.(LOCALE_COOKIE_NAME)?.value ?? null,
    acceptLanguage: Astro.request.headers.get('accept-language'),
  });

  const t = (key: string, params?: TranslateParams) => translate(locale, key, params);

  return {
    locale,
    t,
    messages: getMessages(locale),
    buildLocaleUrl: (targetLocale: Locale) => buildLocaleUrl(requestUrl, targetLocale),
  };
}

export function getReadTimeMinutes(value: string | number | null | undefined): number | null {
  if (typeof value === 'number' && Number.isFinite(value)) {
    return value;
  }

  const match = String(value || '').match(/\d+/);
  if (!match) {
    return null;
  }

  return Number(match[0]);
}

export function formatReadTime(
  _locale: Locale,
  value: string | number | null | undefined,
  t: (key: string, params?: TranslateParams) => string
): string {
  const minutes = getReadTimeMinutes(value);
  if (minutes === null) {
    return String(value || '');
  }

  return t('common.readTimeMinutes', { count: minutes });
}
