import React from "react";
import { createRoot } from "react-dom/client";

type InteractiveProps = {
  id: string;
  label: string;
  caption?: string;
  description?: string;
  fallback?: string;
  attrs?: Record<string, string>;
};

type InteractiveModule = {
  default: React.ComponentType<InteractiveProps>;
};

const modules = import.meta.glob<InteractiveModule>("./*/index.tsx");

function readProps(element: HTMLElement): InteractiveProps {
  const encoded = element.dataset.interactiveProps;
  if (!encoded) {
    return {
      id: element.dataset.interactiveId ?? "",
      label: "",
    };
  }

  try {
    return JSON.parse(decodeURIComponent(encoded)) as InteractiveProps;
  } catch {
    return {
      id: element.dataset.interactiveId ?? "",
      label: "",
      fallback: element.textContent?.trim() ?? "",
    };
  }
}

async function mountInteractive(element: HTMLElement) {
  const id = element.dataset.interactiveId;
  if (!id || element.dataset.interactiveMounted) return;

  const modulePath = `./${id}/index.tsx`;
  const loader = modules[modulePath];
  if (!loader) {
    element.dataset.interactiveState = "missing-component";
    return;
  }

  element.dataset.interactiveMounted = "true";
  element.dataset.interactiveState = "loading";

  try {
    const props = readProps(element);
    const { default: Component } = await loader();
    element.replaceChildren();
    createRoot(element).render(<Component {...props} />);
    element.dataset.interactiveState = "ready";
  } catch (error) {
    element.dataset.interactiveState = "failed";
    console.error(`Failed to mount interactive "${id}"`, error);
  }
}

function mountAllInteractives() {
  document
    .querySelectorAll<HTMLElement>(".interactive-mount[data-interactive-id]")
    .forEach((element) => {
      void mountInteractive(element);
    });
}

if (document.readyState === "loading") {
  document.addEventListener("DOMContentLoaded", mountAllInteractives, { once: true });
} else {
  mountAllInteractives();
}
