import type i18next from "i18next";
import { createI18nInstance } from "./config.js";
import { isLanguage } from "./resolver.js";

interface I18nPayload {
  locale: string;
  resources: Record<string, Record<string, unknown>>;
}

/**
 * Serializes the loaded locale bundle from an i18next instance into a JSON
 * string suitable for injection into the SSR HTML under `window.__I18N__`.
 */
export function serializeI18nForHydration(i18n: typeof i18next): string {
  const locale = i18n.language;
  const resources: Record<string, Record<string, unknown>> = {};

  const namespaces = Array.isArray(i18n.options.ns)
    ? i18n.options.ns
    : ([i18n.options.ns].filter(Boolean) as string[]);

  for (const ns of namespaces) {
    const bundle = i18n.getResourceBundle(locale, ns) as
      | Record<string, unknown>
      | undefined;
    if (bundle) {
      resources[ns] = bundle;
    }
  }

  const payload: I18nPayload = { locale, resources };
  return JSON.stringify(payload);
}

/**
 * Rehydrates an i18next instance from the SSR-injected `window.__I18N__` payload.
 * Called once on the client before React hydration begins.
 */
export async function hydrateI18nFromWindow(): Promise<typeof i18next> {
  const raw = (globalThis as Record<string, unknown>).__I18N__ as
    | I18nPayload
    | undefined;
  if (!raw) {
    throw new Error(
      "Cannot hydrate i18n: globalThis.__I18N__ is not set. " +
        "Ensure the SSR payload includes the serialized i18n data.",
    );
  }

  const locale = raw.locale;
  if (!isLanguage(locale)) {
    throw new Error(
      `Cannot hydrate i18n: invalid locale "${locale}" in __I18N__ payload.`,
    );
  }

  return createI18nInstance({
    locale,
    initialResources: raw.resources,
  });
}
