import { useEffect, useRef, useState } from "react";

declare global {
  interface Window {
    MathJax?: {
      startup?: { promise?: Promise<void> };
      typesetPromise?: (elements?: Element[]) => Promise<void>;
      [key: string]: any;
    };
  }
}

interface MediaFile {
  id: number;
  fileName: string;
  mediaUrl: string;
}

interface LaTextContainerProps {
  html: string;
  latex: string;
  mediaFiles?: MediaFile[];
}

let mathJaxPromise: Promise<void> | null = null;

const loadMathJax = () => {
  if (mathJaxPromise) return mathJaxPromise;

  mathJaxPromise = new Promise<void>((resolve, reject) => {
    if (window.MathJax?.typesetPromise) {
      resolve();
      return;
    }

    (window as any).MathJax = {
      tex: {
        inlineMath: [["$$$", "$$$"]],
        displayMath: [["$$$$$$", "$$$$$$"]],
        processEscapes: true,
      },
      options: {
        skipHtmlTags: ["script", "noscript", "style", "textarea", "pre", "code"],
      },
      startup: { typeset: false },
    };

    const script = document.createElement("script");
    script.id = "mathjax-script";
    script.src = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js";
    script.async = true;

    script.onload = () => {
      window.MathJax?.startup?.promise?.then(resolve).catch(reject);
    };

    script.onerror = reject;
    document.head.appendChild(script);
  });

  return mathJaxPromise;
};

const replaceImages = (html: string, latex: string, mediaFiles?: MediaFile[]) => {
  const parser = new DOMParser();
  const doc = parser.parseFromString(html, "text/html");

  const latexImageNames = Array.from(latex.matchAll(/\\includegraphics\{(.+?)\}/g)).map(
    (match) => match[1]
  );

  const imgs = doc.querySelectorAll<HTMLImageElement>("img.tex-graphics");

  imgs.forEach((img, idx) => {
    const imageName = latexImageNames[idx];
    if (!imageName || !mediaFiles) return;
    const mediaFile = mediaFiles.find((f) => f.fileName === imageName);
    if (mediaFile) img.src = mediaFile.mediaUrl;
  });

  return doc.body.innerHTML;
};

const LaTextContainer: React.FC<LaTextContainerProps> = ({ html, latex, mediaFiles }) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const [processedHtml, setProcessedHtml] = useState<string>(html);

  // 1️⃣ Обновляем HTML при изменении входных данных
  useEffect(() => {
    setProcessedHtml(replaceImages(html, latex, mediaFiles));
  }, [html, latex, mediaFiles]);

  // 2️⃣ После рендера обновленного HTML применяем MathJax
  useEffect(() => {
    const renderMath = () => {
      if (containerRef.current && window.MathJax?.typesetPromise) {
        window.MathJax.typesetPromise([containerRef.current]).catch(console.error);
      }
    };

    loadMathJax().then(renderMath).catch(console.error);
  }, [processedHtml]); // 👈 ключевой момент — триггерим именно по processedHtml

  return (
    <div
      className="latex-container"
      ref={containerRef}
      dangerouslySetInnerHTML={{ __html: processedHtml }}
    />
  );
};

export default LaTextContainer;
