"use client";

import * as React from "react";
import { useTheme } from "next-themes";
import { cn } from "@/lib/utils";

type MermaidApi = {
  initialize: (config: Record<string, unknown>) => void;
  render: (id: string, code: string) => Promise<{ svg: string; bindFunctions?: (el: Element) => void }>;
};

let mermaidPromise: Promise<MermaidApi> | null = null;
let lastTheme: string | null = null;

/**
 * Lazy-load Mermaid only the first time a mermaid block appears in a document.
 * The library is ~500KB so we keep it out of the main bundle entirely.
 */
async function loadMermaid(theme: string): Promise<MermaidApi> {
  if (!mermaidPromise) {
    mermaidPromise = import("mermaid").then((mod) => {
      const api = (mod.default ?? mod) as unknown as MermaidApi;
      api.initialize({
        startOnLoad: false,
        securityLevel: "strict",
        theme: theme === "dark" ? "dark" : "default",
        fontFamily: "ui-sans-serif, system-ui, -apple-system",
      });
      lastTheme = theme;
      return api;
    });
  } else if (lastTheme !== theme) {
    // Theme change — re-initialize without re-importing.
    mermaidPromise = mermaidPromise.then((api) => {
      api.initialize({
        startOnLoad: false,
        securityLevel: "strict",
        theme: theme === "dark" ? "dark" : "default",
        fontFamily: "ui-sans-serif, system-ui, -apple-system",
      });
      lastTheme = theme;
      return api;
    });
  }
  return mermaidPromise;
}

type Props = {
  code: string;
  className?: string;
};

let renderId = 0;

export function MermaidBlock({ code, className }: Props) {
  const { resolvedTheme } = useTheme();
  const theme = resolvedTheme === "dark" ? "dark" : "light";
  const [svg, setSvg] = React.useState<string | null>(null);
  const [error, setError] = React.useState<string | null>(null);
  const idRef = React.useRef(`mermaid-${++renderId}`);

  React.useEffect(() => {
    let cancelled = false;
    setError(null);
    loadMermaid(theme)
      .then((api) => api.render(idRef.current, code))
      .then((result) => {
        if (!cancelled) setSvg(result.svg);
      })
      .catch((err: unknown) => {
        if (!cancelled) setError(err instanceof Error ? err.message : String(err));
      });
    return () => {
      cancelled = true;
    };
  }, [code, theme]);

  if (error) {
    return (
      <div
        className={cn(
          "rounded-lg border border-destructive/40 bg-destructive/5 p-4 text-sm",
          className,
        )}
      >
        <div className="mb-1 font-medium text-destructive">Mermaid render error</div>
        <pre className="overflow-auto whitespace-pre-wrap text-xs text-destructive/80">
          {error}
        </pre>
      </div>
    );
  }

  if (!svg) {
    return (
      <div
        className={cn(
          "grid h-32 place-items-center rounded-lg border bg-muted/30 text-xs text-muted-foreground",
          className,
        )}
      >
        Rendering diagram…
      </div>
    );
  }

  return (
    <div
      className={cn("my-4 flex justify-center overflow-x-auto rounded-lg border bg-card p-4", className)}
      dangerouslySetInnerHTML={{ __html: svg }}
    />
  );
}
