import { useEffect, useRef, type ReactNode } from "react";
import { useI18n } from "@/lib/i18n";

type Props = {
    children: ReactNode;
};

const SKIP_TEXT_SELECTOR =
    "code, pre, kbd, samp, textarea, script, style, [contenteditable='true'], [data-no-translate]";
const SKIP_ATTRIBUTE_SELECTOR =
    "code, pre, kbd, samp, script, style, [contenteditable='true'], [data-no-translate]";
const TRANSLATABLE_ATTRIBUTES = ["aria-label", "title", "placeholder", "alt"];

/**
 * Bridges legacy literal UI copy to the server-provided translation dictionary.
 * Only exact dictionary matches are changed; code samples and editable content
 * are excluded. New DOM nodes are processed incrementally for live trading views.
 */
export function LegacyTextLocalizer({ children }: Props) {
    const rootRef = useRef<HTMLDivElement>(null);
    const { t, locale } = useI18n();

    useEffect(() => {
        // Observe the document body so Radix dialogs, popovers, and toasts
        // rendered through portals are localized alongside the active page.
        const root = document.body;
        if (!root || typeof MutationObserver === "undefined") return;

        const translateValue = (value: string): string => {
            const normalized = value.replace(/\s+/g, " ").trim();
            if (!normalized || normalized.length > 320) return value;

            const translated = t(normalized);
            if (translated === normalized) return value;

            const leading = value.match(/^\s*/)?.[0] ?? "";
            const trailing = value.match(/\s*$/)?.[0] ?? "";
            return `${leading}${translated}${trailing}`;
        };

        const localizeTextNode = (node: Node) => {
            if (node.nodeType !== Node.TEXT_NODE) return;
            const parent = node.parentElement;
            if (!parent || parent.closest(SKIP_TEXT_SELECTOR)) return;
            const original = node.nodeValue ?? "";
            const translated = translateValue(original);
            if (translated !== original) node.nodeValue = translated;
        };

        const localizeAttributes = (element: Element) => {
            if (element.closest(SKIP_ATTRIBUTE_SELECTOR)) return;
            for (const attribute of TRANSLATABLE_ATTRIBUTES) {
                const value = element.getAttribute(attribute);
                if (value === null) continue;
                const translated = translateValue(value);
                if (translated !== value) {
                    element.setAttribute(attribute, translated);
                }
            }
        };

        const localizeElement = (element: Element) => {
            localizeAttributes(element);
            for (const nested of element.querySelectorAll<HTMLElement>(
                "[aria-label], [title], [placeholder], [alt]",
            )) {
                localizeAttributes(nested);
            }

            const walker = document.createTreeWalker(
                element,
                NodeFilter.SHOW_TEXT,
            );
            let node = walker.nextNode();
            while (node) {
                localizeTextNode(node);
                node = walker.nextNode();
            }
        };

        const localizeRoot = () => {
            const walker = document.createTreeWalker(
                root,
                NodeFilter.SHOW_TEXT,
            );
            let node = walker.nextNode();
            while (node) {
                localizeTextNode(node);
                node = walker.nextNode();
            }
            for (const element of root.querySelectorAll<HTMLElement>(
                "[aria-label], [title], [placeholder], [alt]",
            )) {
                if (element.closest(SKIP_ATTRIBUTE_SELECTOR)) continue;
                for (const attribute of TRANSLATABLE_ATTRIBUTES) {
                    const value = element.getAttribute(attribute);
                    if (value === null) continue;
                    const translated = translateValue(value);
                    if (translated !== value) {
                        element.setAttribute(attribute, translated);
                    }
                }
            }
        };

        localizeRoot();

        const observer = new MutationObserver((records) => {
            for (const record of records) {
                if (record.type === "characterData") {
                    localizeTextNode(record.target);
                } else if (record.type === "attributes") {
                    localizeAttributes(record.target as Element);
                }
                for (const addedNode of record.addedNodes) {
                    if (addedNode.nodeType === Node.TEXT_NODE) {
                        localizeTextNode(addedNode);
                    } else if (addedNode.nodeType === Node.ELEMENT_NODE) {
                        localizeElement(addedNode as Element);
                    }
                }
            }
        });
        observer.observe(root, {
            childList: true,
            subtree: true,
            characterData: true,
            attributes: true,
            attributeFilter: TRANSLATABLE_ATTRIBUTES,
        });

        return () => observer.disconnect();
    }, [locale, t]);

    return (
        <div ref={rootRef} className="contents">
            {children}
        </div>
    );
}
