/**
 * GET /api/artifact-sandbox
 *
 * Serves the artifact renderer HTML with all library scripts inlined
 * from local files (public/sandbox-libs/). Zero CDN dependency — the
 * libraries are read from disk, not fetched from the network.
 *
 * Security: sandbox="allow-scripts" without allow-same-origin.
 */

import { NextResponse } from "next/server";
import { readFileSync } from "fs";
import path from "path";

export const dynamic = "force-dynamic";

// ─── Load scripts from disk (once per cold start) ───────────────────────────

interface ScriptBundle {
  react: string;
  reactDom: string;
  propTypes: string;
  recharts: string;
  lucide: string;
  babel: string;
}

let cachedBundle: ScriptBundle | null = null;

function getBundle(): ScriptBundle {
  if (cachedBundle) return cachedBundle;

  const libDir = path.join(process.cwd(), "public", "sandbox-libs");
  cachedBundle = {
    react:     readFileSync(path.join(libDir, "react.min.js"), "utf-8"),
    reactDom:  readFileSync(path.join(libDir, "react-dom.min.js"), "utf-8"),
    propTypes: readFileSync(path.join(libDir, "prop-types.min.js"), "utf-8"),
    recharts:  readFileSync(path.join(libDir, "recharts.js"), "utf-8"),
    lucide:    readFileSync(path.join(libDir, "lucide.min.js"), "utf-8"),
    babel:     readFileSync(path.join(libDir, "babel.min.js"), "utf-8"),
  };
  return cachedBundle;
}

// ─── HTML template ──────────────────────────────────────────────────────────

function buildHtml(b: ScriptBundle): string {
  // Escape </script> sequences inside inlined bundles to prevent
  // premature closing of the <script> block.
  const esc = (s: string) => s.replace(/<\/script>/gi, "<\\/script>");

  return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Security-Policy" content="script-src 'unsafe-inline' 'unsafe-eval' https://cdn.tailwindcss.com; object-src 'none';">
<title>Artifact Sandbox</title>
<script>
// Suppress errors injected by browser extensions (MetaMask, wallets, etc.)
// before any library scripts run so they don't poison the error relay.
window.addEventListener("error", function(e) {
  if (e.message && /MetaMask|ethereum|web3|phantom|solana|coinbase|keplr|rabby/i.test(e.message)) {
    e.preventDefault(); e.stopPropagation(); return true;
  }
}, true);
</script>
<script>${esc(b.react)}<\/script>
<script>${esc(b.reactDom)}<\/script>
<script>${esc(b.propTypes)}<\/script>
<script>${esc(b.recharts)}<\/script>
<script>${esc(b.lucide)}<\/script>
<script>${esc(b.babel)}<\/script>
<script src="https://cdn.tailwindcss.com"></script>
<style>
  html, body { margin: 0; padding: 0; background: #0f172a; color: #f8fafc; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
  #root { min-height: 100vh; padding: 16px; }
  .error { padding: 16px; color: #fca5a5; font-family: monospace; font-size: 12px; white-space: pre-wrap; }
  .loading { display: flex; align-items: center; justify-content: center; min-height: 200px; color: #94a3b8; font-size: 12px; }
</style>
</head>
<body class="bg-slate-900 text-slate-50">
<div id="root"><div class="loading">Waiting for code...</div></div>

<script>
  window.__artifactErrorPosted = false;
  window.__artifactPostError = function(rawMessage, missing) {
    if (window.__artifactErrorPosted) return;
    window.__artifactErrorPosted = true;
    window.parent.postMessage({ source: "meseo-artifact", type: "error", message: rawMessage, missing: missing || [] }, "*");
  };
  window.addEventListener("error", function(e) { window.__artifactPostError(e.message || "Unknown error"); });
  window.addEventListener("unhandledrejection", function(e) {
    var msg = e.reason && e.reason.message ? e.reason.message : String(e.reason);
    window.__artifactPostError(msg);
  });
</script>

<script>
  function createLucideReactIcon(iconKey) {
    return function LucideIcon(props) {
      if (!window.lucide || !window.lucide.icons || !window.lucide.icons[iconKey]) {
        return window.React.createElement("span", null, "?");
      }
      var def = window.lucide.icons[iconKey];
      var children = def[2] || [];
      var size = props.size || 24;
      var className = props.className;
      var rest = {};
      for (var k in props) if (k !== "className" && k !== "size" && props.hasOwnProperty(k)) rest[k] = props[k];
      return window.React.createElement(
        "svg",
        Object.assign({ xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className: className }, rest),
        children.map(function(child, i) { return window.React.createElement(child[0], Object.assign({ key: i }, child[1])); })
      );
    };
  }

  window.__artifactGlobals = function() {
    var R = window.React;
    var RC = window.Recharts || {};
    var mk = createLucideReactIcon;
    return {
      React: R, useState: R.useState, useMemo: R.useMemo, useEffect: R.useEffect, useRef: R.useRef,
      LineChart: RC.LineChart, BarChart: RC.BarChart, AreaChart: RC.AreaChart,
      PieChart: RC.PieChart, ComposedChart: RC.ComposedChart, RadarChart: RC.RadarChart,
      Line: RC.Line, Bar: RC.Bar, Area: RC.Area, Pie: RC.Pie, Cell: RC.Cell,
      Radar: RC.Radar, PolarGrid: RC.PolarGrid, PolarAngleAxis: RC.PolarAngleAxis, PolarRadiusAxis: RC.PolarRadiusAxis,
      XAxis: RC.XAxis, YAxis: RC.YAxis, CartesianGrid: RC.CartesianGrid,
      Tooltip: RC.Tooltip, Legend: RC.Legend, ResponsiveContainer: RC.ResponsiveContainer,
      ReferenceLine: RC.ReferenceLine, ReferenceDot: RC.ReferenceDot,
      ArrowDown: mk("arrow-down"), ArrowDownRight: mk("arrow-down-right"), ArrowLeft: mk("arrow-left"), ArrowRight: mk("arrow-right"),
      ArrowUp: mk("arrow-up"), ArrowUpRight: mk("arrow-up-right"), ChevronDown: mk("chevron-down"), ChevronLeft: mk("chevron-left"),
      ChevronRight: mk("chevron-right"), ChevronUp: mk("chevron-up"), MoreHorizontal: mk("more-horizontal"), MoreVertical: mk("more-vertical"),
      TrendingDown: mk("trending-down"), TrendingUp: mk("trending-up"), Activity: mk("activity"), BarChart2: mk("bar-chart-2"),
      BarChart3: mk("bar-chart-3"), DollarSign: mk("dollar-sign"), Percent: mk("percent"), Target: mk("target"),
      AlertCircle: mk("alert-circle"), AlertTriangle: mk("alert-triangle"), Check: mk("check"), CheckCircle: mk("check-circle"),
      Info: mk("info"), XCircle: mk("x-circle"),
      Bell: mk("bell"), Bookmark: mk("bookmark"), Calendar: mk("calendar"), Clock: mk("clock"), Copy: mk("copy"),
      Crosshair: mk("crosshair"), Download: mk("download"), Edit: mk("edit"), ExternalLink: mk("external-link"),
      Eye: mk("eye"), EyeOff: mk("eye-off"), Filter: mk("filter"), Flag: mk("flag"), Grid: mk("grid"),
      Hash: mk("hash"), Heart: mk("heart"), Layers: mk("layers"), Layout: mk("layout"), Link: mk("link"),
      List: mk("list"), Lock: mk("lock"), Menu: mk("menu"), Minus: mk("minus"), Navigation: mk("navigation"),
      Plus: mk("plus"), Save: mk("save"), Search: mk("search"), Settings: mk("settings"), Share: mk("share"),
      Sparkles: mk("sparkles"), Tag: mk("tag"), Trash: mk("trash"), Unlock: mk("unlock"), Upload: mk("upload"),
      X: mk("x"), Zap: mk("zap"),
      Award: mk("award"), Briefcase: mk("briefcase"), Building: mk("building"), Compass: mk("compass"),
      CreditCard: mk("credit-card"), Gift: mk("gift"), Globe: mk("globe"), Home: mk("home"), Mail: mk("mail"),
      MapPin: mk("map-pin"), Phone: mk("phone"), ShoppingCart: mk("shopping-cart"), User: mk("user"), Users: mk("users"),
      Camera: mk("camera"), FileText: mk("file-text"), Folder: mk("folder"), Image: mk("image"), Mic: mk("mic"),
      Music: mk("music"), Printer: mk("printer"), Video: mk("video"), Volume2: mk("volume-2"),
      Battery: mk("battery"), Cloud: mk("cloud"), Code: mk("code"), Cpu: mk("cpu"), Database: mk("database"),
      HardDrive: mk("hard-drive"), Monitor: mk("monitor"), Server: mk("server"), Smartphone: mk("smartphone"),
      Tablet: mk("tablet"), Terminal: mk("terminal"), Wifi: mk("wifi"),
      Flame: mk("flame"), Lightbulb: mk("lightbulb"), Moon: mk("moon"), Rocket: mk("rocket"),
      Shield: mk("shield"), Star: mk("star"), Sun: mk("sun"),
    };
  };
</script>

<script>
  window.addEventListener("message", function(event) {
    if (!event.data || event.data.source !== "meseo-artifact-code") return;
    var userCode = event.data.code || "";
    window.__artifactErrorPosted = false;

    if (!window.React || !window.ReactDOM || !window.Recharts || !window.Babel) {
      window.__artifactPostError("Required libraries failed to initialize. Try refreshing.", []);
      return;
    }

    var g = window.__artifactGlobals();
    var globalKeys = Object.keys(g);
    var globalValues = globalKeys.map(function(k) { return g[k]; });
    var React = g.React;

    var src = userCode;
    src = src.replace(/^import\\s[^;]*;?\\s*$/gm, "");
    src = src.replace(/^export\\s+default\\s+/m, "window.__ArtifactComponent = ");
    src = src.replace(/^export\\s+/gm, "");

    try {
      var transformed = window.Babel.transform(src, {
        presets: [["react", { runtime: "classic" }], "typescript"],
        filename: "artifact.tsx",
      }).code;

      var fn = new Function(...globalKeys, transformed);
      fn(...globalValues);

      var Component = window.__ArtifactComponent;
      if (typeof Component !== "function") throw new Error("Artifact did not export a default component");

      class ErrorBoundary extends React.Component {
        constructor(props) { super(props); this.state = { error: null }; }
        static getDerivedStateFromError(error) { return { error }; }
        componentDidCatch(error) { window.__artifactPostError(error && error.message ? error.message : "Unknown render error"); }
        render() {
          if (this.state.error) return React.createElement("div", { className: "error" }, "Chart failed to render.");
          return this.props.children;
        }
      }

      var root = window.ReactDOM.createRoot(document.getElementById("root"));
      root.render(React.createElement(ErrorBoundary, null, React.createElement(Component)));

      requestAnimationFrame(function() {
        window.parent.postMessage({ source: "meseo-artifact", type: "ready" }, "*");
        var reportHeight = function() { window.parent.postMessage({ source: "meseo-artifact", type: "height", value: document.body.scrollHeight }, "*"); };
        reportHeight();
        if (window.ResizeObserver) { new ResizeObserver(reportHeight).observe(document.body); }
        else { setInterval(reportHeight, 500); }
      });
    } catch (e) {
      var msg = (e && e.message) || String(e);
      window.__artifactPostError(msg);
      document.getElementById("root").innerHTML = '<pre class="error">' + msg.replace(/</g, "&lt;") + '</pre>';
    }
  });

  window.parent.postMessage({ source: "meseo-artifact", type: "sandbox-ready" }, "*");
</script>
</body>
</html>`;
}

// ─── Route handler ──────────────────────────────────────────────────────────

let cachedHtml: string | null = null;

export async function GET() {
  try {
    if (!cachedHtml) {
      const bundle = getBundle();
      cachedHtml = buildHtml(bundle);
    }

    return new NextResponse(cachedHtml, {
      headers: {
        "Content-Type": "text/html; charset=utf-8",
        "Cache-Control": "public, max-age=31536000, immutable",
        "X-Frame-Options": "SAMEORIGIN",
      },
    });
  } catch (err) {
    const msg = err instanceof Error ? err.message : "Unknown error";
    console.error("[artifact-sandbox] Failed to load libraries from disk:", msg);

    return new NextResponse(
      `<!DOCTYPE html><html><body style="background:#0f172a;color:#fca5a5;font-family:monospace;padding:20px;font-size:13px">
<p>Libraries failed to load from disk: ${msg.replace(/</g, "&lt;")}</p>
<script>window.parent.postMessage({source:"meseo-artifact",type:"error",message:"Sandbox libraries failed to load: ${msg.replace(/"/g, '\\"')}",missing:["disk-read"]},"*");<\/script>
</body></html>`,
      {
        headers: { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-cache" },
      },
    );
  }
}
