import React from "react";
import ReactDOM, { type Root } from "react-dom/client";
import SwatchGroup from "../components/SwatchGroup";
import SwatchErrorBoundary from "../components/ErrorBoundary";
import { safeParseJson } from "./debug";

const mountedRoots = new WeakMap<HTMLElement, Root>();

/**
 * Initialize and mount React swatch components
 */
export const initSwatches = ({
  forceRemount = false,
  SwatchGroupComponent = SwatchGroup,
}: {
  forceRemount?: boolean;
  SwatchGroupComponent?: React.ComponentType<any>;
} = {}) => {
  const mountPoints = document.querySelectorAll<HTMLElement>(
    ".b3-wvs-swatches-mount",
  );

  mountPoints.forEach((mount) => {
    const container = mount.closest<HTMLElement>(".b3-wvs-swatches-container");
    if (!container) return;

    if (forceRemount) {
      mountedRoots.get(mount)?.unmount();
      mountedRoots.delete(mount);
      delete mount.dataset.b3WvsMounted;
      container.classList.remove("b3-wvs-initialized");
      container.classList.add("b3-wvs-fallback");
      const original = container.querySelector<HTMLElement>(
        ".b3-wvs-original-select",
      );
      if (original) original.style.display = "";
    }

    // Avoid creating multiple React roots for the same mount.
    if (
      container.classList.contains("b3-wvs-initialized") ||
      mount.dataset.b3WvsMounted === "1"
    ) {
      return;
    }

    const attribute = container.dataset.attribute;
    const swatchesData = safeParseJson(container.dataset.swatches);
    const select = container.querySelector("select");

    if (!attribute || !(select instanceof HTMLSelectElement)) {
      return;
    }

    const root = ReactDOM.createRoot(mount);
    mountedRoots.set(mount, root);
    root.render(
      <React.StrictMode>
        <SwatchErrorBoundary fallbackSelect={select}>
          <SwatchGroupComponent
            attribute={attribute}
            select={select}
            swatches={swatchesData}
          />
        </SwatchErrorBoundary>
      </React.StrictMode>,
    );

    // After successful mount, hide the original select UI.
    mount.dataset.b3WvsMounted = "1";
    container.classList.add("b3-wvs-initialized");
    container.classList.remove("b3-wvs-fallback");
    const original = container.querySelector<HTMLElement>(
      ".b3-wvs-original-select",
    );
    if (original) original.style.display = "none";
  });
};

/**
 * Schedule fallback reveal if swatches don't initialize
 */
let fallbackScheduled = false;
export const scheduleFallbackReveal = () => {
  if (fallbackScheduled) return;
  fallbackScheduled = true;

  // If swatches don't initialize (e.g. a JS error), restore the original select UI.
  // This avoids a blank UI state.
  window.setTimeout(() => {
    const containers = document.querySelectorAll<HTMLElement>(
      ".b3-wvs-swatches-container",
    );
    containers.forEach((container) => {
      if (!container.classList.contains("b3-wvs-initialized")) {
        container.classList.add("b3-wvs-fallback");
      }
    });
  }, 3000);
};
