"use client";

import { useEffect } from "react";

/** Tokens that mix Latin letters with digits, e.g. F300, IP55, 24VDC */
const MIXED_TOKEN =
  /[A-Za-z][A-Za-z0-9.+/-]*\d[A-Za-z0-9.+/-]*|\d+[A-Za-z][A-Za-z0-9.+/-]*/g;

function wrapLatinDigitTokens(root: ParentNode) {
  const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
    acceptNode(node) {
      const parent = node.parentElement;
      if (!parent) return NodeFilter.FILTER_REJECT;
      if (
        parent.closest(
          "script, style, noscript, textarea, code, pre, .latin-digits, [data-no-latin-digits]",
        )
      ) {
        return NodeFilter.FILTER_REJECT;
      }
      return NodeFilter.FILTER_ACCEPT;
    },
  });

  const textNodes: Text[] = [];
  while (walker.nextNode()) {
    textNodes.push(walker.currentNode as Text);
  }

  for (const textNode of textNodes) {
    const value = textNode.nodeValue;
    if (!value || !MIXED_TOKEN.test(value)) continue;
    MIXED_TOKEN.lastIndex = 0;

    const frag = document.createDocumentFragment();
    let lastIndex = 0;

    for (const match of value.matchAll(MIXED_TOKEN)) {
      const start = match.index ?? 0;
      if (start > lastIndex) {
        frag.appendChild(document.createTextNode(value.slice(lastIndex, start)));
      }

      const span = document.createElement("span");
      span.className = "latin-digits";
      span.dir = "ltr";
      span.textContent = match[0];
      frag.appendChild(span);

      lastIndex = start + match[0].length;
    }

    if (lastIndex < value.length) {
      frag.appendChild(document.createTextNode(value.slice(lastIndex)));
    }

    textNode.parentNode?.replaceChild(frag, textNode);
  }
}

/** Keeps Western digits next to English letters site-wide (Iran Yekan FaNum fix). */
export function LatinDigitsEnhancer() {
  useEffect(() => {
    wrapLatinDigitTokens(document.body);

    const observer = new MutationObserver((mutations) => {
      for (const mutation of mutations) {
        for (const node of mutation.addedNodes) {
          if (node.nodeType === Node.ELEMENT_NODE) {
            wrapLatinDigitTokens(node as Element);
          } else if (node.nodeType === Node.TEXT_NODE && node.parentElement) {
            wrapLatinDigitTokens(node.parentElement);
          }
        }
      }
    });

    observer.observe(document.body, { childList: true, subtree: true });
    return () => observer.disconnect();
  }, []);

  return null;
}
