"use client";

import { useState, useRef, useEffect, useCallback } from "react";
import { Copy, Check, Maximize2, Minimize2, RefreshCw, Sparkles, AlertTriangle, Loader2 } from "lucide-react";

// Cache-busting version derived from the deploy's git commit SHA.
// Changes automatically on every Vercel deploy — no manual bumping.
const SANDBOX_VERSION = process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA?.slice(0, 8) || "dev";

/**
 * ArtifactRenderer
 * ─────────────────────
 * Renders an AI-generated JSX artifact in a sandboxed iframe. The iframe
 * loads from /api/artifact-sandbox (a standalone HTML page with React,
 * Recharts, lucide, Tailwind, and Babel). The parent sends the generated
 * JSX code via postMessage; the sandbox transpiles and renders it.
 *
 * Security:
 *   - The iframe uses sandbox="allow-scripts" (NO allow-same-origin)
 *   - This gives the iframe an opaque origin — it cannot access the
 *     parent's cookies, localStorage, or Clerk session
 *   - The generated code runs inside new Function() with explicit globals
 *   - CDN scripts load via the HTML parser (not JS fetch) so they work
 *     without same-origin
 */
interface ArtifactError {
  message: string;
  missing: string[];
}

export function ArtifactRenderer({ title, code, renderError: initialRenderError }: { title: string; code: string; renderError?: string }) {
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const [copied, setCopied] = useState(false);
  const [expanded, setExpanded] = useState(false);
  // Default taller than the old 480px so a short artifact still shows
  // meaningful chart real estate without requiring the user to hit
  // Expand. Dynamic height messages from the sandbox can push this up to
  // 1600 (see onMessage below) or down to the 600 floor.
  const [height, setHeight] = useState(600);
  // Pre-flight error from Layer 3 heuristic check (set before iframe loads)
  const [error, setError] = useState<ArtifactError | null>(
    initialRenderError ? { message: initialRenderError, missing: [] } : null
  );
  const [loading, setLoading] = useState(!initialRenderError);
  const [reloadKey, setReloadKey] = useState(0);
  const sandboxReady = useRef(false);
  const pendingCode = useRef<string | null>(null);

  // Send code to the sandbox iframe via postMessage
  const sendCode = useCallback((codeToSend: string) => {
    if (iframeRef.current?.contentWindow) {
      iframeRef.current.contentWindow.postMessage(
        { source: "meseo-artifact-code", code: codeToSend },
        "*", // The sandbox has an opaque origin, so we must use "*"
      );
    }
  }, []);

  useEffect(() => {
    function onMessage(event: MessageEvent) {
      if (!event.data || typeof event.data !== "object") return;
      if (event.data.source !== "meseo-artifact") return;

      if (event.data.type === "sandbox-ready") {
        sandboxReady.current = true;
        // Send any code that was waiting for the sandbox to load
        if (pendingCode.current) {
          sendCode(pendingCode.current);
          pendingCode.current = null;
        }
        return;
      }
      if (event.data.type === "height" && typeof event.data.value === "number") {
        // Floor at 600px so a short artifact (single KPI row + one chart)
        // doesn't collapse into a tiny box. Cap at 1600px so a runaway
        // dashboard doesn't eat the whole page — Expand still reveals
        // everything via the fullscreen overlay.
        setHeight(Math.max(600, Math.min(1600, event.data.value + 20)));
      }
      if (event.data.type === "error" && typeof event.data.message === "string") {
        const missing: string[] = Array.isArray(event.data.missing) ? event.data.missing : [];
        setError({ message: event.data.message, missing });
        setLoading(false);
      }
      if (event.data.type === "ready") {
        setLoading(false);
        setError(null);
      }
    }
    window.addEventListener("message", onMessage);
    return () => window.removeEventListener("message", onMessage);
  }, [sendCode]);

  // Send code when it changes or when reloadKey changes
  useEffect(() => {
    setLoading(true);
    setError(null);
    if (sandboxReady.current) {
      sendCode(code);
    } else {
      pendingCode.current = code;
    }
  }, [code, reloadKey, sendCode]);

  // On reload, reset the sandbox
  useEffect(() => {
    sandboxReady.current = false;
    pendingCode.current = code;
  }, [reloadKey, code]);

  function handleCopy() {
    navigator.clipboard.writeText(code).catch(() => { /* ignore */ });
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  }

  const frameWrapperCls = expanded
    ? "fixed inset-4 z-50 rounded-2xl border border-slate-700 bg-slate-900 shadow-2xl overflow-hidden flex flex-col"
    : "rounded-xl border border-slate-700 bg-slate-900 overflow-hidden flex flex-col";

  return (
    <>
      {expanded && (
        <div
          className="fixed inset-0 bg-black/60 z-40 backdrop-blur-sm"
          onClick={() => setExpanded(false)}
        />
      )}
      <div className={frameWrapperCls}>
        {/* Toolbar */}
        <div className="flex items-center gap-2 px-3 py-2 border-b border-slate-700 bg-gradient-to-r from-slate-800 to-slate-900 shrink-0">
          <Sparkles className="w-3.5 h-3.5 text-indigo-400 shrink-0" />
          <div className="min-w-0 flex-1">
            <p className="text-[9px] font-bold uppercase tracking-widest text-indigo-400">Generated Artifact</p>
            <p className="text-xs font-semibold text-slate-100 truncate">{title}</p>
          </div>
          <button
            onClick={handleCopy}
            className="flex items-center gap-1 px-2 py-1 rounded text-[10px] font-semibold text-slate-300 hover:bg-slate-700 transition-colors"
            title="Copy JSX"
          >
            {copied ? <Check className="w-3 h-3 text-green-400" /> : <Copy className="w-3 h-3" />}
            {copied ? "Copied" : "Copy JSX"}
          </button>
          <button
            onClick={() => setReloadKey((k) => k + 1)}
            className="flex items-center gap-1 px-2 py-1 rounded text-[10px] font-semibold text-slate-300 hover:bg-slate-700 transition-colors"
            title="Re-render artifact"
          >
            <RefreshCw className="w-3 h-3" />
            Refresh
          </button>
          <button
            onClick={() => setExpanded((v) => !v)}
            className="flex items-center gap-1 px-2 py-1 rounded text-[10px] font-semibold text-slate-300 hover:bg-slate-700 transition-colors"
            title={expanded ? "Collapse" : "Expand"}
          >
            {expanded ? <Minimize2 className="w-3 h-3" /> : <Maximize2 className="w-3 h-3" />}
            {expanded ? "Collapse" : "Expand"}
          </button>
        </div>

        {/* Iframe body — cap at 700px in inline mode so the chat page doesn't
            scroll indefinitely. The Expand button reveals the full artifact
            in a fullscreen overlay. */}
        <div className="relative flex-1 bg-slate-900" style={expanded ? undefined : { height, maxHeight: 700, overflow: "hidden" }}>
          {loading && !error && (
            <div className="absolute inset-0 flex items-center justify-center bg-slate-900 z-10">
              <div className="flex items-center gap-2 text-slate-400 text-xs">
                <Loader2 className="w-4 h-4 animate-spin text-indigo-400" />
                Rendering visualization…
              </div>
            </div>
          )}
          {error && (
            <div className="absolute inset-0 bg-slate-900 z-10 px-6 py-8 overflow-y-auto">
              <div className="max-w-lg mx-auto text-center">
                <div className="w-12 h-12 rounded-full bg-amber-500/10 border border-amber-500/30 flex items-center justify-center mx-auto mb-3">
                  <AlertTriangle className="w-5 h-5 text-amber-400" />
                </div>
                <p className="text-sm font-semibold text-slate-100 mb-1">This chart couldn&apos;t render.</p>
                <p className="text-xs text-slate-400 mb-4">
                  {error.missing.length > 0
                    ? "The AI referenced components that aren't available in the sandbox."
                    : "Click Refresh to try again, or copy the JSX to inspect it."}
                </p>
                <button
                  onClick={() => setReloadKey((k) => k + 1)}
                  className="inline-flex items-center gap-1.5 px-3 py-1.5 bg-indigo-500 hover:bg-indigo-400 rounded text-xs font-semibold text-white transition-colors"
                >
                  <RefreshCw className="w-3 h-3" />
                  Refresh
                </button>

                {error.missing.length > 0 && (
                  <div className="mt-4 p-3 bg-amber-500/5 border border-amber-500/20 rounded-lg text-left">
                    <p className="text-[10px] font-bold uppercase tracking-widest text-amber-400 mb-1.5">
                      Unsupported components
                    </p>
                    <div className="flex flex-wrap gap-1.5">
                      {error.missing.map((name) => (
                        <code
                          key={name}
                          className="px-1.5 py-0.5 bg-slate-800 border border-slate-700 rounded text-[10px] font-mono text-amber-300"
                        >
                          {name}
                        </code>
                      ))}
                    </div>
                  </div>
                )}

                <details className="mt-4 text-left group">
                  <summary className="text-[10px] font-bold uppercase tracking-widest text-slate-500 cursor-pointer hover:text-slate-400 select-none list-none flex items-center gap-1">
                    <span className="group-open:rotate-90 transition-transform inline-block">▸</span>
                    Debug details
                  </summary>
                  <div className="mt-2 p-3 bg-slate-950 rounded border border-slate-800 text-[10px] text-slate-300 font-mono break-all leading-relaxed max-h-40 overflow-y-auto whitespace-pre-wrap">
                    {error.message}
                  </div>
                </details>
              </div>
            </div>
          )}
          <iframe
            key={reloadKey}
            ref={iframeRef}
            src={`/api/artifact-sandbox?v=${SANDBOX_VERSION}`}
            sandbox="allow-scripts"
            className="w-full h-full border-0"
            title={title}
          />
        </div>
      </div>
    </>
  );
}

