// Shared right-side drawer + Source Details panel with multi-tab correlation
const { useState: useStateD, useEffect: useEffectD, useMemo: useMemoD } = React;
const {
  IconX, IconCopy, IconChevRight, IconChevDown, IconChevLeft,
  IconSearch, IconClock, IconWarnTri, IconJSON, IconTable, IconCaretRight,
} = window.Icons;

// ─── Generic right-side drawer
function Drawer({ open, width = 1120, onClose, children, headerless = false }) {
  if (!open) return null;
  return (
    <div style={{
      position: "fixed", inset: 0, zIndex: 60,
      display: "flex", justifyContent: "flex-end",
      pointerEvents: "auto",
    }}>
      {/* Scrim */}
      <div className="drawer-scrim" onClick={onClose} style={{
        position: "absolute", inset: 0,
        background: "rgba(20,20,27,0.32)",
        backdropFilter: "blur(1px)",
      }}/>
      {/* Panel */}
      <div className="drawer-panel" style={{
        position: "relative",
        width: `min(${width}px, 96vw)`,
        background: "var(--surface)",
        borderLeft: "1px solid var(--border)",
        boxShadow: "-12px 0 32px -8px rgba(20,20,27,0.18)",
        display: "flex", flexDirection: "column",
      }}>
        {children}
      </div>
    </div>
  );
}

function DrawerHeader({ title, subtitle, onClose, right }) {
  return (
    <div style={{
      padding: "16px 24px 14px",
      borderBottom: "1px solid var(--border)",
      display: "flex", alignItems: "flex-start", justifyContent: "space-between",
      flexShrink: 0,
    }}>
      <div>
        <div style={{ fontSize: 18, fontWeight: 600, color: "var(--ink)", letterSpacing: "-0.01em" }}>
          {title}
        </div>
        {subtitle && <div style={{ fontSize: 12, color: "var(--muted)", marginTop: 2 }}>{subtitle}</div>}
      </div>
      <div style={{ display: "flex", gap: 4, alignItems: "center" }}>
        {right}
        <button className="icon-btn" onClick={onClose}
                style={{ width: 28, height: 28, borderRadius: "50%", color: "var(--muted)" }}>
          <IconX size={14}/>
        </button>
      </div>
    </div>
  );
}

// ─── Source Details drawer — multi-tab correlation
// tabs: JSON · Table · Logs · Metrics · Traces (+ AI sparkle)
function SourceDetailsDrawer({ open, source, onClose }) {
  const [tab, setTab] = useStateD("json");
  useEffectD(() => { if (open) setTab("json"); }, [open, source]);
  if (!open || !source) return null;

  return (
    <Drawer open={open} onClose={onClose} width={1120}>
      <DrawerHeader title="Source Details" onClose={onClose} />
      <div style={{ flex: 1, display: "flex", flexDirection: "column", minHeight: 0 }}>
        <SDTabBar tab={tab} onTab={setTab} />
        <div style={{ flex: 1, minHeight: 0, overflow: "auto" }}>
          {tab === "json"    && <SDJson source={source}/>}
          {tab === "table"   && <SDTable source={source}/>}
          {tab === "logs"    && <SDLogs source={source}/>}
          {tab === "metrics" && <SDMetrics source={source}/>}
          {tab === "traces"  && <SDTraces source={source}/>}
        </div>
      </div>
    </Drawer>
  );
}

function SDTabBar({ tab, onTab }) {
  const Tab = ({ k, label, ai }) => (
    <button onClick={() => onTab(k)} className={`tab-underline ${tab === k ? "active" : ""}`}
      style={{
        background: "none", border: "none", padding: "10px 0",
        cursor: "pointer", textTransform: "none",
        position: "relative",
      }}>
      {label}
      {ai && <span style={{ marginLeft: 4 }}>
        <svg width="12" height="12" viewBox="0 0 24 24" fill="none">
          <defs><linearGradient id="ai-tab" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stopColor="#F0A6FF"/><stop offset="1" stopColor="#5C5DBC"/></linearGradient></defs>
          <path d="M11 2 L13 8.5 L19.5 10.5 L13 12.5 L11 19 L9 12.5 L2.5 10.5 L9 8.5 Z" fill="url(#ai-tab)"/>
        </svg>
      </span>}
    </button>
  );
  return (
    <div style={{
      display: "flex", gap: 28,
      padding: "0 24px",
      borderBottom: "1px solid var(--border)",
      background: "var(--canvas)",
      flexShrink: 0,
    }}>
      <Tab k="json"    label="JSON" />
      <Tab k="table"   label="Table" />
      <Tab k="logs"    label="Logs" />
      <Tab k="metrics" label="Metrics" />
      <Tab k="traces"  label="Traces" ai />
    </div>
  );
}

// ─── JSON tab: render the source as colored JSON tree
function SDJson({ source }) {
  return (
    <div style={{ position: "relative", padding: "16px 24px" }}>
      <button className="icon-btn" style={{
        position: "absolute", top: 16, right: 24,
        width: 28, height: 28, color: "var(--muted)",
      }}>
        <IconCopy size={13}/>
      </button>
      <pre className="mono" style={{
        margin: 0, fontSize: 13, lineHeight: 1.7, color: "var(--ink-2)",
        whiteSpace: "pre-wrap", wordBreak: "break-word",
      }}>
        {"{\n"}
        {Object.entries(source).map(([k, v], i, arr) => (
          <span key={k}>
            {"  "}<span style={{ color: "var(--ink-2)", display: "inline-block", width: 12 }}>▾</span>{" "}
            <span className="lg-key">{k}</span>
            <span style={{ color: "var(--muted)" }}>: </span>
            <span style={{ color: typeof v === "number" ? "oklch(0.50 0.11 180)" : "var(--err)" }}>
              {typeof v === "string" ? `${v}` : String(v)}
            </span>
            {i < arr.length - 1 ? "," : ""}
            {"\n"}
          </span>
        ))}
        {"}"}
      </pre>
    </div>
  );
}

// ─── Table tab: same data, table layout
function SDTable({ source }) {
  return (
    <div style={{ padding: "8px 0" }}>
      <div style={{
        display: "grid", gridTemplateColumns: "260px 1fr",
        padding: "10px 24px",
        background: "var(--canvas)",
        borderBottom: "1px solid var(--border)",
        fontSize: 11, fontWeight: 600, color: "var(--ink-2)",
      }}>
        <span>Field</span>
        <span>Value</span>
      </div>
      {Object.entries(source).map(([k, v]) => (
        <div key={k} style={{
          display: "grid", gridTemplateColumns: "260px 1fr",
          padding: "8px 24px",
          borderBottom: "1px solid var(--border)",
          fontSize: 12,
        }}>
          <span className="mono lg-key">{k}</span>
          <span className="mono" style={{ color: "var(--ink)", wordBreak: "break-all" }}>{String(v)}</span>
        </div>
      ))}
    </div>
  );
}

// ─── Logs tab: correlated logs (other rows from the seeded dataset)
function SDLogs({ source }) {
  const allRows = (window.Data.LOG_ROWS_DEFAULT || []).slice(0, 14);
  return (
    <div>
      <div style={{
        display: "grid", gridTemplateColumns: "180px 140px 1fr 90px",
        padding: "10px 24px",
        background: "var(--canvas)",
        borderBottom: "1px solid var(--border)",
        fontSize: 11, fontWeight: 600, color: "var(--ink-2)",
      }}>
        <span>timestamp <span style={{ color: "var(--muted)", fontWeight: 400 }}>(Asia/Calcutta)</span></span>
        <span>stream_name</span>
        <span>body</span>
        <span>severity</span>
      </div>
      {allRows.map((row, i) => {
        const body = row.source.body || JSON.stringify(row.source).slice(0, 80);
        const isErr = /ERROR|warn/i.test(body);
        return (
          <div key={i} style={{
            display: "grid", gridTemplateColumns: "180px 140px 1fr 90px",
            padding: "6px 24px",
            borderBottom: "1px solid var(--border)",
            borderLeft: `3px solid ${isErr ? "var(--err)" : "var(--accent)"}`,
            marginLeft: -3,
            fontSize: 11.5, alignItems: "center",
          }}>
            <span className="mono" style={{ color: "var(--ink-2)", display: "flex", alignItems: "center", gap: 5 }}>
              <IconChevRight size={9} style={{ color: "var(--muted-2)" }}/>
              {row.date} {row.ts}
            </span>
            <span style={{ color: "var(--ink)" }}>otel_demo</span>
            <span className="mono" style={{ color: "var(--ink)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
              {body}
            </span>
            <span className="mono" style={{
              color: isErr ? "var(--err)" : "var(--accent-fg)",
              fontWeight: 600, fontSize: 11,
            }}>{isErr ? "ERROR" : "INFO"}</span>
          </div>
        );
      })}
    </div>
  );
}

// ─── Metrics tab: Infra/Network sub-tabs + selectable field list + chart grid
const SD_METRIC_LIST = [
  { key: "container_cpu_time",          group: "infra", selected: true,  max: 1.35, unit: "M" },
  { key: "container_cpu_usage",         group: "infra", selected: true,  max: 0.15, unit: "" },
  { key: "container_filesystem_available", group: "infra", selected: true,  max: 18.54, unit: "GB" },
  { key: "container_filesystem_capacity",  group: "infra", selected: true,  max: 46.57, unit: "GB" },
  { key: "container_filesystem_usage",  group: "infra", selected: true,  max: 117.19, unit: "KB" },
  { key: "container_memory_major_page_faults", group: "infra", selected: true, max: 250, unit: "" },
  { key: "container_memory_page_faults", group: "infra" },
  { key: "container_memory_rss",        group: "infra" },
  { key: "container_memory_usage",      group: "infra" },
  { key: "container_memory_working_set", group: "infra" },
  { key: "k8s_container_ready",         group: "infra" },
  { key: "k8s_container_restarts",      group: "infra" },
  { key: "k8s_deployment_available",    group: "infra" },
  { key: "k8s_deployment_desired",      group: "infra" },
  { key: "k8s_pod_cpu_request_utilization", group: "infra" },
  { key: "k8s_pod_cpu_time",            group: "infra" },
  { key: "k8s_pod_cpu_usage",           group: "infra" },
  { key: "k8s_pod_filesystem_available", group: "infra" },
  { key: "k8s_pod_filesystem_capacity", group: "infra" },
  { key: "k8s_pod_filesystem_usage",    group: "infra" },
  { key: "k8s_pod_memory_major_page_faults", group: "infra" },
  { key: "k8s_pod_memory_page_faults",  group: "infra" },
  { key: "k8s_pod_memory_request_utilization", group: "infra" },
  { key: "k8s_pod_memory_rss",          group: "infra" },
  { key: "k8s_pod_memory_usage",        group: "infra" },
  { key: "k8s_pod_memory_working_set",  group: "infra" },
  { key: "k8s_pod_phase",               group: "infra" },
  { key: "k8s_volume_available",        group: "infra" },
  { key: "k8s_volume_capacity",         group: "infra" },
];

function SDMetrics({ source }) {
  const [group, setGroup] = useStateD("infra");
  const [selected, setSelected] = useStateD(() =>
    new Set(SD_METRIC_LIST.filter(m => m.selected).map(m => m.key))
  );
  const filtered = SD_METRIC_LIST.filter(m => m.group === group);
  const drawn = filtered.filter(m => selected.has(m.key));

  return (
    <div style={{ display: "flex", height: "100%", minHeight: 0 }}>
      {/* Field selector */}
      <div style={{
        width: 320, flexShrink: 0,
        borderRight: "1px solid var(--border)",
        background: "var(--surface)",
        display: "flex", flexDirection: "column",
        minHeight: 0,
      }}>
        <div style={{
          padding: "10px 16px 8px",
          display: "flex", alignItems: "center", gap: 8,
        }}>
          <div style={{
            display: "flex", alignItems: "center", gap: 8,
            padding: "6px 10px", flex: 1,
            background: "var(--canvas)", border: "1px solid var(--border)", borderRadius: 6,
          }}>
            <IconSearch size={13} style={{ color: "var(--muted)" }} />
            <input placeholder="Search for a field" style={{
              border: "none", outline: "none", background: "transparent",
              fontSize: 12, color: "var(--ink)", flex: 1,
              fontFamily: "inherit",
            }}/>
          </div>
        </div>

        <div style={{ padding: "0 16px 8px" }}>
          <button onClick={() => setGroup("infra")} style={{
            display: "flex", alignItems: "center", width: "100%",
            padding: "8px 10px",
            background: group === "infra" ? "var(--accent-bg)" : "var(--rail)",
            border: "1px solid " + (group === "infra" ? "var(--accent-line)" : "var(--border)"),
            borderRadius: 6, cursor: "pointer",
          }}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"><rect x="3" y="4" width="18" height="6" rx="1"/><rect x="3" y="14" width="18" height="6" rx="1"/></svg>
            <span style={{ marginLeft: 8, fontSize: 12, fontWeight: 600, color: "var(--ink)" }}>INFRA</span>
            <span className="mono pill" style={{
              marginLeft: 6, background: "var(--accent-bg)", color: "var(--accent-fg)",
              border: "1px solid var(--accent-line)",
            }}>39</span>
            <div style={{ flex: 1 }}/>
            <button className="btn-ghost" style={{ height: 22, padding: "0 6px", fontSize: 11, color: "var(--accent-fg)" }} onClick={e => { e.stopPropagation(); setSelected(new Set(SD_METRIC_LIST.filter(m => m.group === group).map(m => m.key))); }}>All</button>
            <button className="btn-ghost" style={{ height: 22, padding: "0 6px", fontSize: 11, color: "var(--muted)" }} onClick={e => { e.stopPropagation(); setSelected(new Set()); }}>None</button>
          </button>
        </div>

        <div style={{ flex: 1, overflowY: "auto", padding: "0 8px 12px" }}>
          {filtered.map(m => {
            const on = selected.has(m.key);
            return (
              <label key={m.key} style={{
                display: "flex", alignItems: "center", gap: 10,
                padding: "5px 8px", cursor: "pointer",
                fontSize: 12, color: "var(--ink)",
                borderRadius: 4,
              }}
              onMouseEnter={e => e.currentTarget.style.background = "var(--rail)"}
              onMouseLeave={e => e.currentTarget.style.background = "transparent"}>
                <input type="checkbox" checked={on} onChange={() => {
                  const next = new Set(selected);
                  if (on) next.delete(m.key); else next.add(m.key);
                  setSelected(next);
                }}
                style={{ accentColor: "var(--accent)" }}/>
                <span className="mono">{m.key}</span>
              </label>
            );
          })}
        </div>

        <div style={{
          padding: "8px 16px",
          borderTop: "1px solid var(--border)",
          fontSize: 11, color: "var(--muted)",
        }}>
          {selected.size} of {filtered.length} selected
        </div>
      </div>

      {/* Charts grid */}
      <div style={{ flex: 1, overflowY: "auto", padding: 16, minHeight: 0 }}>
        <div style={{
          display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))",
          gap: 14,
        }}>
          {drawn.map(m => <MetricCardLite key={m.key} metric={m}/>)}
        </div>
        {drawn.length === 0 && (
          <div style={{
            padding: 60, textAlign: "center", color: "var(--muted)",
            fontSize: 13,
          }}>Select metrics on the left to chart them.</div>
        )}
      </div>
    </div>
  );
}

// Deterministic series for SD metric card
function sdSeries(seed, n, max) {
  let s = seed;
  const r = () => { s = (s * 9301 + 49297) % 233280; return s / 233280; };
  const out = [];
  let v = max * 0.6;
  for (let i = 0; i < n; i++) {
    v += (r() - 0.5) * max * 0.08;
    v = Math.max(max * 0.05, Math.min(max * 0.98, v));
    out.push(v);
  }
  return out;
}

function MetricCardLite({ metric }) {
  const data = useMemoD(() => sdSeries(metric.key.length * 7, 60, metric.max || 100), [metric.key]);
  const [hoverIdx, setHoverIdx] = useStateD(null);

  const W = 260, H = 110;
  const padL = 4, padR = 4, padT = 6, padB = 18;
  const chartW = W - padL - padR;
  const chartH = H - padT - padB;
  const max = Math.max(...data) * 1.05;
  const min = 0;
  const stepX = chartW / (data.length - 1);
  const pts = data.map((v, i) => [padL + i * stepX, padT + chartH - (v / max) * chartH]);
  const path = pts.map((p, i) => `${i === 0 ? "M" : "L"}${p[0].toFixed(1)} ${p[1].toFixed(1)}`).join(" ");
  const area = `${path} L ${padL + chartW} ${padT + chartH} L ${padL} ${padT + chartH} Z`;
  const yTicks = 5;

  const tooltip = hoverIdx !== null ? data[hoverIdx] : null;
  const hoverX = hoverIdx !== null ? pts[hoverIdx][0] : 0;
  const hoverY = hoverIdx !== null ? pts[hoverIdx][1] : 0;

  return (
    <div style={{
      background: "var(--surface)", border: "1px solid var(--border)",
      borderRadius: 6, padding: "10px 12px",
    }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 6 }}>
        <span className="mono" style={{ fontSize: 11, fontWeight: 600, color: "var(--ink)" }}>{metric.key}</span>
      </div>
      <div style={{ position: "relative" }}
           onMouseMove={(e) => {
             const r = e.currentTarget.getBoundingClientRect();
             const x = (e.clientX - r.left) / r.width * W;
             const idx = Math.max(0, Math.min(data.length - 1, Math.round((x - padL) / stepX)));
             setHoverIdx(idx);
           }}
           onMouseLeave={() => setHoverIdx(null)}>
        <svg width="100%" height={H} viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none">
          {/* Y grid */}
          {Array.from({ length: yTicks }, (_, i) => {
            const y = padT + (chartH / (yTicks - 1)) * i;
            const val = max * (1 - i / (yTicks - 1));
            return (
              <g key={i}>
                <line x1={padL} y1={y} x2={padL + chartW} y2={y} stroke="var(--border)" strokeWidth="0.5" strokeDasharray="2 3"/>
                <text x={padL + 2} y={y - 1} fontSize="8" fontFamily="JetBrains Mono" fill="var(--muted)">
                  {formatMetric(val, metric.unit)}
                </text>
              </g>
            );
          })}
          <path d={area} fill="var(--err)" opacity=".10"/>
          <path d={path} stroke="var(--err)" strokeWidth="1.4" fill="none"/>
          {/* Hover line + dot */}
          {hoverIdx !== null && (
            <g>
              <line x1={hoverX} y1={padT} x2={hoverX} y2={padT + chartH} stroke="var(--ink-2)" strokeWidth="0.5" strokeDasharray="2 2"/>
              <circle cx={hoverX} cy={hoverY} r="3" fill="var(--err)" stroke="white" strokeWidth="1"/>
            </g>
          )}
          {/* X labels */}
          {["20:01","20:03","20:05","20:07"].map((t, i) => (
            <text key={t} x={padL + (chartW / 3) * i + 8} y={H - 4} fontSize="8.5" fontFamily="JetBrains Mono" fill="var(--muted)">{t}</text>
          ))}
        </svg>
        {hoverIdx !== null && tooltip !== null && (
          <div style={{
            position: "absolute",
            left: `${(hoverX / W) * 100}%`,
            top: `${(hoverY / H) * 100}%`,
            transform: "translate(8px, -50%)",
            background: "var(--ink)",
            color: "var(--canvas)",
            padding: "4px 8px", borderRadius: 4,
            fontSize: 10, fontFamily: "JetBrains Mono",
            pointerEvents: "none",
            whiteSpace: "nowrap",
            zIndex: 2,
          }}>
            2026-04-01 20:0{Math.floor(hoverIdx / 10)}:{String((hoverIdx % 10) * 6).padStart(2, "0")}
            <br/>
            <span style={{ color: "#FF9D9D" }}>●</span> {formatMetric(tooltip, metric.unit)}
          </div>
        )}
      </div>
    </div>
  );
}

function formatMetric(v, unit) {
  if (v >= 1e6) return (v / 1e6).toFixed(2) + "M";
  if (v >= 1e3) return (v / 1e3).toFixed(2) + "K";
  if (unit === "GB") return v.toFixed(2) + "GB";
  if (unit === "KB") return v.toFixed(2) + "KB";
  if (unit === "M")  return v.toFixed(2) + "M";
  return v.toFixed(2);
}

// ─── Traces tab: Waterfall + Flame Graph + Service Map sub-tabs
function SDTraces({ source }) {
  const [sub, setSub] = useStateD("waterfall");
  const [selectedSpan, setSelectedSpan] = useStateD("otel-3");

  // Compact trace data scoped to this log row
  const trace = {
    name: "order-consumed",
    startedAt: "1 Apr 11:00:04:946",
    ago: "9h ago",
    id: "e49386c6dd7224a208f8c11b629197a5",
    spans: 3, errors: 1,
    tree: [
      { id: "acc-1",  service: "accounting", op: "order-consumed",   kind: "l", status: 200, depth: 0, dur: 10360, start: 0 },
      { id: "acc-2",  service: "accounting", op: "orders receive",   kind: "i", status: 200, depth: 1, dur: 57.98, start: 100 },
      { id: "otel-3", service: "accounting", op: "otel",             kind: "i", status: 500, depth: 1, dur: 122.92, start: 200, err: true },
    ],
  };

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", minHeight: 0 }}>
      {/* Trace header */}
      <div style={{
        padding: "12px 24px 10px",
        borderBottom: "1px solid var(--border)",
        display: "flex", alignItems: "center", gap: 12,
        background: "var(--canvas)",
      }}>
        <span style={{ fontSize: 16, fontWeight: 600, color: "var(--ink)" }}>{trace.name}</span>
        <span style={{ fontSize: 12, color: "var(--muted)" }}>
          {trace.startedAt} ({trace.ago})
        </span>
        <span style={{ width: 1, height: 18, background: "var(--border)" }}/>
        <span style={{ fontSize: 12, color: "var(--muted)" }}>Trace ID:</span>
        <span className="mono" style={{ fontSize: 12, color: "var(--ink)", fontWeight: 600 }}>{trace.id}</span>
        <button className="icon-btn" style={{ width: 20, height: 20 }}><IconCopy size={11}/></button>
        <div style={{ flex: 1 }}/>
        <span className="mono pill" style={{
          background: "var(--accent-bg)", color: "var(--accent-fg)",
          padding: "3px 9px", border: "1px solid var(--accent-line)",
        }}>{trace.spans} spans</span>
        <span className="mono pill" style={{
          background: "var(--err-bg)", color: "var(--err)",
          padding: "3px 9px", border: "1px solid rgba(220,64,64,.18)",
        }}>{trace.errors} errors</span>
      </div>

      {/* Sub-tabs */}
      <div style={{
        display: "flex", gap: 24, padding: "8px 24px",
        borderBottom: "1px solid var(--border)",
      }}>
        {[["waterfall","Waterfall"], ["flame","Flame Graph"], ["servicemap","Service Map"]].map(([k, label]) => (
          <button key={k} onClick={() => setSub(k)}
                  className={`tab-underline ${sub === k ? "active" : ""}`}
                  style={{ background: "none", border: "none", padding: "4px 0", cursor: "pointer" }}>
            {label}
          </button>
        ))}
      </div>

      {/* Content */}
      <div style={{ flex: 1, overflow: "auto", minHeight: 0 }}>
        {sub === "waterfall" && (
          <TraceWaterfallCompact trace={trace} selected={selectedSpan} onSelect={setSelectedSpan}/>
        )}
        {sub === "flame" && <TraceFlameCompact trace={trace}/>}
        {sub === "servicemap" && <TraceServiceMapCompact/>}
      </div>
    </div>
  );
}

// Span-kind badge
function KindBadgeSD({ k }) {
  const palette = {
    l: { bg: "#E2EAFF", fg: "#3D6EF0" },
    i: { bg: "#FCEFC9", fg: "#A77622" },
    s: { bg: "#DEF2E5", fg: "#2E9D63" },
    c: { bg: "#E9DEF5", fg: "#7A52E0" },
  };
  const c = palette[k] || palette.s;
  return (
    <span className="mono" style={{
      display: "inline-flex", alignItems: "center", justifyContent: "center",
      width: 14, height: 14, borderRadius: 3,
      background: c.bg, color: c.fg,
      fontSize: 9, fontWeight: 700,
    }}>{k}</span>
  );
}

function TraceWaterfallCompact({ trace, selected, onSelect }) {
  const W = 1080;
  const treeW = 320;
  const timelineW = W - treeW;
  const maxT = Math.max(...trace.tree.map(s => s.start + s.dur));
  const ticks = [0, maxT * 0.25, maxT * 0.5, maxT * 0.75, maxT];

  // Span detail (right panel for selected span)
  const sel = trace.tree.find(s => s.id === selected) || trace.tree[0];

  return (
    <div style={{ display: "flex", minHeight: 0 }}>
      {/* Tree + timeline */}
      <div style={{ flex: 1, minWidth: 0, borderRight: "1px solid var(--border)" }}>
        {/* Header row */}
        <div style={{
          display: "grid", gridTemplateColumns: `${treeW}px 1fr`,
          fontSize: 11, color: "var(--ink-2)", fontWeight: 600,
          padding: "8px 0", borderBottom: "1px solid var(--border)",
          background: "var(--canvas)",
        }}>
          <span style={{ paddingLeft: 16 }}>Operation Name</span>
          <div style={{ display: "flex", justifyContent: "space-between", padding: "0 12px", color: "var(--muted)" }}>
            {ticks.map((t, i) => (
              <span key={i} className="mono" style={{ fontSize: 10 }}>
                {formatDur(t)}
              </span>
            ))}
          </div>
        </div>

        {trace.tree.map(s => {
          const isSel = s.id === selected;
          const left = (s.start / maxT) * timelineW;
          const width = Math.max(8, (s.dur / maxT) * timelineW);
          return (
            <div key={s.id} onClick={() => onSelect(s.id)}
                 style={{
                   display: "grid", gridTemplateColumns: `${treeW}px 1fr`,
                   alignItems: "center",
                   padding: "8px 0", borderBottom: "1px solid var(--border)",
                   background: isSel ? "var(--accent-bg)" : "transparent",
                   cursor: "pointer",
                 }}>
              <div style={{
                paddingLeft: 16 + s.depth * 18,
                display: "flex", alignItems: "center", gap: 8,
                fontSize: 12, position: "relative",
              }}>
                {s.depth > 0 && (
                  <span style={{
                    position: "absolute", left: 8 + (s.depth - 1) * 18 + 16, top: -8, bottom: -8,
                    borderLeft: "1px dashed var(--border-2)",
                  }}/>
                )}
                {s.err && <span style={{ width: 6, height: 6, borderRadius: "50%", background: "var(--err)" }}/>}
                <span className="mono" style={{
                  fontSize: 9, color: "var(--muted)", fontWeight: 700,
                  background: "var(--canvas)", border: "1px solid var(--border)",
                  borderRadius: 3, padding: "0 4px", minWidth: 16, textAlign: "center",
                }}>{s.depth === 0 ? "2" : "1"}</span>
                <span style={{ color: "var(--accent-fg)", fontWeight: 500 }}>{s.service}</span>
                <KindBadgeSD k={s.kind}/>
                <span style={{ color: "var(--ink-2)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{s.op}</span>
                <span style={{ flex: 1 }}/>
                <span className="mono" style={{ fontSize: 11, color: s.err ? "var(--err)" : "var(--ok)", fontWeight: 600, paddingRight: 8 }}>
                  {s.status}
                </span>
              </div>
              <div style={{ position: "relative", height: 14, padding: "0 12px" }}>
                <div style={{
                  position: "absolute", left: 12 + left, top: 2, height: 10,
                  width, background: s.err ? "var(--err)" : (s.depth === 0 ? "#3D6EF0" : "#7A52E0"),
                  borderRadius: 2,
                }}/>
                <div style={{
                  position: "absolute", left: 12 + left, top: 13,
                  fontSize: 9, color: "var(--muted)", fontFamily: "JetBrains Mono",
                }}>{formatDur(s.dur)}</div>
              </div>
            </div>
          );
        })}
      </div>

      {/* Selected span detail */}
      <div style={{ width: 360, flexShrink: 0, background: "var(--surface)" }}>
        <div style={{
          padding: "10px 16px", borderBottom: "1px solid var(--border)",
          fontSize: 13, fontWeight: 600, color: "var(--ink)",
        }}>
          {sel.op}
        </div>
        <div style={{ padding: 12, display: "flex", flexDirection: "column", gap: 8 }}>
          <ChipRow label="Service" value={sel.service}/>
          <ChipRow label="Duration" value={formatDur(sel.dur)}/>
          <ChipRow label="Start" value={formatDur(sel.start)}/>
          <ChipRow label="Status" value={sel.status} crit={sel.err}/>
          <div style={{ marginTop: 6, borderTop: "1px solid var(--border)", paddingTop: 8 }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: "var(--ink-2)", marginBottom: 4 }}>Tags</div>
            <div className="mono" style={{ fontSize: 11, color: "var(--ink-2)", lineHeight: 1.8 }}>
              {sel.err
                ? <>
                    <div><span className="lg-key">db_system</span>: postgresql</div>
                    <div><span className="lg-key">db_name</span>: otel</div>
                    <div><span className="lg-key">db_statement</span>: INSERT INTO "order"...</div>
                    <div><span className="lg-key">net_peer_name</span>: postgresql</div>
                    <div><span className="lg-key">net_peer_ip</span>: 172.20.166.142</div>
                  </>
                : <>
                    <div><span className="lg-key">service_k8s_namespace</span>: default</div>
                    <div><span className="lg-key">service_k8s_pod_name</span>: accounting-84458d886f-ftt29</div>
                    <div><span className="lg-key">service_k8s_node_name</span>: ip-10-1-2-215.us-east-2</div>
                  </>}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function ChipRow({ label, value, crit }) {
  return (
    <div style={{
      display: "flex", alignItems: "center", justifyContent: "space-between",
      padding: "4px 8px",
      background: "var(--canvas)", border: "1px solid var(--border)", borderRadius: 5,
    }}>
      <span style={{ fontSize: 11, color: "var(--muted)" }}>{label}</span>
      <span className="mono" style={{
        fontSize: 12, color: crit ? "var(--err)" : "var(--ink)", fontWeight: 600,
      }}>{value}</span>
    </div>
  );
}

function formatDur(us) {
  if (us >= 1000) return (us / 1000).toFixed(2) + "ms";
  if (us >= 1)    return us.toFixed(2) + "us";
  return us + "ns";
}

// Compact flame view: scaled span rectangles
function TraceFlameCompact({ trace }) {
  const W = 1080, H = 200;
  const padL = 24, padR = 24;
  const maxT = Math.max(...trace.tree.map(s => s.start + s.dur));
  const chartW = W - padL - padR;

  return (
    <div style={{ padding: 20 }}>
      <div style={{ fontSize: 12, color: "var(--ink-2)", marginBottom: 12 }}>
        <span className="mono" style={{ fontWeight: 600, color: "var(--ink)" }}>{trace.spans} spans</span>
        <span style={{ margin: "0 8px", color: "var(--muted-2)" }}>·</span>
        <span className="mono" style={{ fontWeight: 600, color: "var(--ink)" }}>2 depth</span>
      </div>
      <div style={{ position: "relative" }}>
        <div style={{
          display: "flex", justifyContent: "space-between",
          padding: `0 ${padL}px 6px`,
          fontSize: 10, color: "var(--muted)", fontFamily: "JetBrains Mono",
        }}>
          <span>0us</span><span>{formatDur(maxT * 0.25)}</span>
          <span>{formatDur(maxT * 0.5)}</span>
          <span>{formatDur(maxT * 0.75)}</span>
          <span>{formatDur(maxT)}</span>
        </div>
        <div style={{ position: "relative", height: 90 }}>
          {trace.tree.map((s, i) => {
            const left = padL + (s.start / maxT) * chartW;
            const width = Math.max(40, (s.dur / maxT) * chartW);
            const top = s.depth * 28;
            return (
              <div key={s.id} title={s.op} style={{
                position: "absolute", left, top, width, height: 24,
                background: s.err ? "var(--err)" : (s.depth === 0 ? "#3D6EF0" : "#E0A53C"),
                color: "white", borderRadius: 2,
                fontSize: 11, fontWeight: 500,
                padding: "0 8px",
                display: "flex", alignItems: "center",
                overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap",
                border: i === 0 ? "2px solid #2A2D5C" : "1px solid rgba(255,255,255,.3)",
              }}>{s.service}.{s.op}</div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

function TraceServiceMapCompact() {
  // 3-node service graph: load-generator → accounting → postgresql
  return (
    <div style={{ padding: 24 }}>
      <svg width="100%" height="240" viewBox="0 0 720 240">
        <defs>
          <marker id="sd-arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
            <path d="M0 0L10 5L0 10z" fill="var(--border-strong)"/>
          </marker>
        </defs>
        {/* edges */}
        <path d="M150 120 Q 270 120 360 120" stroke="var(--border-strong)" strokeWidth="1.6" fill="none" markerEnd="url(#sd-arrow)"/>
        <path d="M460 120 Q 540 120 580 120" stroke="var(--err)" strokeWidth="1.8" fill="none" markerEnd="url(#sd-arrow)"/>
        {/* nodes */}
        {[
          { x: 100, y: 120, color: "#3D6EF0", label: "load-generator" },
          { x: 410, y: 120, color: "#2E9D63", label: "accounting" },
          { x: 630, y: 120, color: "#DC4040", label: "postgresql" },
        ].map((n, i) => (
          <g key={i}>
            <rect x={n.x - 60} y={n.y - 22} width="120" height="44" rx="6"
                  fill="var(--surface)" stroke={n.color} strokeWidth="2"/>
            <circle cx={n.x - 46} cy={n.y} r="5" fill={n.color}/>
            <text x={n.x - 36} y={n.y + 4} fontSize="12" fill="var(--ink)" fontWeight="600">{n.label}</text>
          </g>
        ))}
        <text x="240" y="100" fontSize="10" fill="var(--muted)" fontFamily="JetBrains Mono" textAnchor="middle">2 calls</text>
        <text x="520" y="100" fontSize="10" fill="var(--err)" fontFamily="JetBrains Mono" textAnchor="middle">1 error</text>
      </svg>
    </div>
  );
}

// ─── Animations
(function () {
  if (document.getElementById("drawer-anim")) return;
  const s = document.createElement("style");
  s.id = "drawer-anim";
  s.textContent = `
    .drawer-panel, .drawer-scrim { opacity: 1 !important; }
  `;
  document.head.appendChild(s);
})();

window.Drawer = Drawer;
window.DrawerHeader = DrawerHeader;
window.SourceDetailsDrawer = SourceDetailsDrawer;
