/**
 * Zentrale Übersetzungen (i18n-ähnlich).
 * Quelle: CMS translation_bundle (API, Middleware setzt Astro.locals.translations).
 * Wird in Layout geladen und über TranslationProvider/Svelte-Context bereitgestellt.
 *
 * Wichtig für client:load-Inseln: useTranslate() hat dort keinen Context und beim SSR kein window,
 * daher fehlen Übersetzungen (es erscheint der Key). Lösung: Übersetzungen als Prop von der
 * Astro-Seite übergeben und t(translations, key, replacements) nutzen. Siehe .cursor/rules/translations-i18n.mdc.
 */

import { getContext } from "svelte";

export type Translations = Record<string, string>;

/** Context-Key für die t-Funktion (von TranslationProvider gesetzt). */
export const T_CONTEXT_KEY = Symbol("translations.t");

/** Platzhalter für Ersetzung: z. B. { name: "Max" } ersetzt {{name}} im Übersetzungstext. */
export type TranslationReplacements = Record<string, string | number>;

/** t(key) oder t(key, { placeholder: value }) – mit optionalen Ersetzungen für {{placeholder}}. */
export type TFunction = (
  key: string,
  replacements?: TranslationReplacements,
) => string;

/**
 * Ersetzt {{name}} im Text durch replacements[name]; fehlende Keys bleiben als {{name}}.
 */
export function replacePlaceholders(
  text: string,
  replacements?: TranslationReplacements | null,
): string {
  if (!replacements || typeof text !== "string") return text;
  return text.replace(/\{\{(\w+)\}\}/g, (_, name: string) => {
    const val = replacements[name];
    return val !== undefined && val !== null ? String(val) : `{{${name}}}`;
  });
}

/** Liest Übersetzungen aus window oder aus script#astro-translations (Fallback für Inseln). */
function getTranslationsFromWindow(): Translations | null {
  if (typeof window === "undefined") return null;
  const w = window as unknown as { __TRANSLATIONS__?: Translations };
  if (w.__TRANSLATIONS__ && typeof w.__TRANSLATIONS__ === "object") return w.__TRANSLATIONS__;
  try {
    const el = document.getElementById("astro-translations");
    const json =
      el?.getAttribute("data-translations") ??
      (el as HTMLScriptElement | null)?.textContent?.trim();
    if (json) {
      const parsed = JSON.parse(json) as Translations;
      w.__TRANSLATIONS__ = parsed;
      return parsed;
    }
  } catch {
    /* ignore */
  }
  return null;
}

/**
 * t-Funktion aus Svelte-Context oder aus window.__TRANSLATIONS__.
 * Nur zuverlässig innerhalb des TranslationProvider-Baums. Für client:load-Inseln:
 * Übersetzungen als Prop übergeben und statische t(translations, key) nutzen (siehe Regel translations-i18n).
 */
export function useTranslate(): TFunction {
  const fromContext = getContext<TFunction | undefined>(T_CONTEXT_KEY);
  if (fromContext) return fromContext;
  const warnedKeys = new Set<string>();
  return (key: string, replacements?: TranslationReplacements): string => {
    const translations = getTranslationsFromWindow();
    const raw = translations?.[key] ?? key;
    if (
      typeof import.meta.env !== "undefined" &&
      import.meta.env.DEV &&
      raw === key &&
      key.length > 0 &&
      !warnedKeys.has(key)
    ) {
      warnedKeys.add(key);
      console.warn(
        `[translations] Key "${key}" in Insel nicht gefunden (kein Context/window). ` +
          `Übersetzungen als Prop von der Astro-Seite übergeben und t(translations, key) nutzen. Siehe .cursor/rules/translations-i18n.mdc`,
      );
    }
    return replacePlaceholders(raw, replacements);
  };
}

/** Bekannte Übersetzungs-Keys – nur hier eintragen, Nutzung über T.xy (Autocomplete, keine Tippfehler). */
const TRANSLATION_KEYS = [
  "searchable_text_help",
  "searchable_text_help_aria",
  "searchable_text_placeholder",
  "searchable_text_search_aria",
  "searchable_text_clear_search",
  "searchable_text_tag_all",
  "searchable_text_no_results",
  "searchable_text_count_all",
  "searchable_text_count_filtered",
  "searchable_text_copy_aria",
  "searchable_text_copy_button",
  "searchable_text_copied",
  "searchable_text_untitled",
  "footer_copyright",
  "nav_start",
  "nav_posts",
  "nav_home",
  "header_search_open",
  "header_search_close",
  "header_menu_open",
  "header_menu_close",
  "header_nav_aria",
  "header_overlay_close",
  "header_social_aria",
  "site_name_fallback",
  "pagination_prev",
  "pagination_next",
  "blog_tag_all",
  "blog_filter_aria",
  "blog_count",
  "page_404_title",
  "page_404_text",
  "page_404_back",
  "posts_title",
  "posts_subtitle",
  "posts_tag_title",
  "posts_tag_subtitle",
  "posts_cms_error",
  "iframe_activate_aria",
  "iframe_missing",
  "image_gallery_swipe_aria",
  "image_gallery_prev_aria",
  "image_gallery_next_aria",
  "image_gallery_position_aria",
  "image_gallery_slide_aria",
  "image_gallery_empty",
  "youtube_missing",
  "youtube_title_fallback",
  "calendar_prev_month",
  "calendar_next_month",
  "calendar_weekday_mo",
  "calendar_weekday_di",
  "calendar_weekday_mi",
  "calendar_weekday_do",
  "calendar_weekday_fr",
  "calendar_weekday_sa",
  "calendar_weekday_so",
  "calendar_more_info",
  "calendar_no_events",
  "calendar_time_suffix",
  "calendar_select_day",
  "calendar_next_events",
  "calendar_show_more",
  "calendar_show_less",
  "post_comments",
  "post_map",
  "post_map_open_osm",
  "post_map_activate",
  "post_overview_all",
  "blog_search_label",
  "blog_search_placeholder",
  "blog_search_clear",
  "blog_year_label",
  "blog_year_all",
  "blog_upcoming_events",
  "blog_results_count",
  "blog_results_for",
  "blog_results_in_year",
  "blog_filter_reset",
  "blog_no_results",
  "blog_rss_subscribe",
] as const;

export type TranslationKey = (typeof TRANSLATION_KEYS)[number];

/** Keys als Objekt: T.searchable_text_help → "searchable_text_help" (für t(T.xy)). */
export const T: { [K in TranslationKey]: K } = Object.fromEntries(
  TRANSLATION_KEYS.map((k) => [k, k]),
) as { [K in TranslationKey]: K };

/**
 * Platzhalter im CMS-Text: {{name}} wird durch t(key, { name: "Wert" }) ersetzt.
 * Beispiel im CMS: "Hallo {{user}}, du hast {{count}} Einträge."
 * Aufruf: t(T.xyz, { user: "Max", count: 5 })
 */

/**
 * Gibt den übersetzten Text für key zurück, optional mit Ersetzung von {{placeholder}}.
 * Fallback: key selbst (damit fehlende Einträge im CMS erkennbar sind).
 * Nutzbar in Astro und in Svelte-Inseln: Übersetzungen von der Astro-Seite als Prop übergeben,
 * dann in der Komponente z. B. `t(translations ?? null, T.xy, { count: 5 })` (siehe BlogOverview.svelte).
 */
export function t(
  translations: Translations | null | undefined,
  key: string,
  replacements?: TranslationReplacements,
): string {
  if (!key) return key;
  const raw = translations?.[key] ?? key;
  return replacePlaceholders(raw, replacements);
}
