import {
  Children,
  cloneElement,
  isValidElement,
  type ReactElement,
  type ReactNode,
} from "react";

import { translateStaticUiText } from "@/lib/i18n-dictionaries";
import type { SupportedLocale } from "@/lib/i18n-config";

const LOCALIZED_STRING_PROPS = [
  "aria-label",
  "aria-description",
  "alt",
  "buttonLabel",
  "description",
  "emptyLabel",
  "helpText",
  "label",
  "pendingLabel",
  "placeholder",
  "title",
] as const;

function localizeNode(node: ReactNode, locale: SupportedLocale): ReactNode {
  if (typeof node === "string") {
    return translateStaticUiText(locale, node);
  }

  if (Array.isArray(node)) {
    return node.map((child) => localizeNode(child, locale));
  }

  if (!isValidElement(node)) {
    return node;
  }

  const element = node as ReactElement<Record<string, unknown>>;

  if (element.props["data-i18n-skip"] === true) {
    return element;
  }

  const nextProps: Record<string, unknown> = {};

  for (const propName of LOCALIZED_STRING_PROPS) {
    const value = element.props[propName];

    if (typeof value === "string") {
      nextProps[propName] = translateStaticUiText(locale, value);
    }
  }

  if ("children" in element.props) {
    nextProps.children = Children.map(element.props.children as ReactNode, (child) =>
      localizeNode(child, locale),
    );
  }

  return cloneElement(element, nextProps);
}

export function localizeStaticUiValue<T>(
  value: T,
  locale: SupportedLocale,
): T {
  if (typeof value === "string") {
    return translateStaticUiText(locale, value) as T;
  }

  if (Array.isArray(value)) {
    return value.map((item) => localizeStaticUiValue(item, locale)) as T;
  }

  if (value && typeof value === "object") {
    return Object.fromEntries(
      Object.entries(value).map(([key, item]) => [
        key,
        localizeStaticUiValue(item, locale),
      ]),
    ) as T;
  }

  return value;
}

export function ServerStaticUiLocalizer({
  children,
  locale,
}: {
  children: ReactNode;
  locale: SupportedLocale;
}) {
  return <>{localizeNode(children, locale)}</>;
}
