"use client";

import Link from "next/link";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";

import { DataTable } from "@/components/data-table";
import { SectionHeading } from "@/components/section-heading";
import { SignalLineChart } from "@/components/line-chart";
import {
  getCompositeDecomposition,
  getCompositeSignalLatest,
  getCompositeSignalSeries,
  getOptionsDashboardLatest,
  getOptionsDashboardSeries,
  getPerpsDashboardLatest,
  getPerpsDashboardSeries,
  getSignalLatest,
  getSignalSeries,
} from "@/lib/api/client";
import type {
  CompositeSignalSummary,
  OptionsDashboardSummary,
  PerpsDashboardSummary,
  SignalSeriesResponse,
  SignalSummary,
} from "@/lib/api/types";
import {
  addWidgetToDashboards,
  createDashboard,
  dashboardEventName,
  loadDashboards,
  saveDashboards,
  type DashboardWidget,
  type DashboardWidgetFamily,
  type DashboardWidgetKind,
  type SavedDashboard,
} from "@/lib/dashboards";
import { formatMetricValue, formatTimestamp } from "@/lib/format";
import { DEFAULT_INITIAL_RANGE_DAYS, rangeStartIso, rangeWindowIso, seriesMaxPoints } from "@/lib/ranges";
import { useStream } from "@/lib/ws/use-stream";

import { COMPOSITE_DASHBOARDS } from "../composite/composite-config";
import { OPTIONS_DASHBOARDS } from "../options/options-config";
import { PERPS_DASHBOARDS } from "../perps/perps-config";

type WidgetPayload =
  | {
      kind: "chart";
      data: Record<string, string | number | null>[];
      lines: Array<{ key: string; label: string; color: string; yAxisId?: "left" | "right" }>;
      title: string;
    }
  | {
      kind: "card";
      metrics: Array<{ key: string; value: unknown }>;
      title: string;
    }
  | {
      kind: "table";
      columns: string[];
      rows: Record<string, unknown>[];
      title: string;
    };

type SourceItem = {
  family: DashboardWidgetFamily;
  id: string;
  title: string;
  subtitle: string;
  filters: Record<string, string>;
};

type WidgetLoadState = {
  loading: boolean;
  payload: WidgetPayload | null;
};

const DASHBOARD_WIDGET_RANGE_DAYS = DEFAULT_INITIAL_RANGE_DAYS;
const DASHBOARD_WIDGET_MAX_POINTS = seriesMaxPoints(DASHBOARD_WIDGET_RANGE_DAYS);
const DASHBOARD_FETCH_CONCURRENCY = 4;

function signalChartLines(signalId: string) {
  if (signalId.includes("razor")) {
    return [
      { key: "razor_pnl", label: "Razor PnL", color: "#6ac2ff" },
      { key: "razor_vrp", label: "Razor VRP", color: "#ffd166" },
      { key: "razor_pnl_zscore", label: "PnL Z", color: "#f58549" },
      { key: "razor_vrp_zscore", label: "VRP Z", color: "#8dd3c7" },
    ] as const;
  }
  return [
    { key: "dvol", label: "DVOL", color: "#6ac2ff" },
    { key: "rvvix_14d", label: "rVVIX 14D", color: "#ffd166" },
    { key: "rvvix_30d", label: "rVVIX 30D", color: "#f58549" },
    { key: "qvvix_30d", label: "qVVIX 30D", color: "#8dd3c7" },
  ] as const;
}

function signalDefaultSource(signalId: string) {
  return signalId.includes("razor") ? "synthetic_7d_atm" : "dvol";
}

function signalCardKeys(signalId: string) {
  return signalId.includes("razor")
    ? ["razor_pnl", "razor_vrp", "razor_pnl_zscore", "razor_vrp_zscore"]
    : ["dvol", "rvvix_14d", "rvvix_30d", "qvvix_30d"];
}

function signalTableRows(series: SignalSeriesResponse) {
  return series.points.slice(-10).reverse().map((point) => ({
    ts: formatTimestamp(point.ts),
    dvol: point.dvol,
    rvvix_14d: point.rvvix_14d,
    rvvix_30d: point.rvvix_30d,
    qvvix_30d: point.qvvix_30d,
    razor_pnl: point.razor_pnl,
    razor_vrp: point.razor_vrp,
    quality: point.quality_flag,
  }));
}

function compactTableColumns(rows: Record<string, unknown>[]) {
  if (rows.length === 0) return [];
  return Object.keys(rows[0]).slice(0, 6);
}

async function loadWidgetPayload(widget: DashboardWidget, referenceTs?: string | null): Promise<WidgetPayload | null> {
  const rangeWindow = referenceTs ? rangeWindowIso(DASHBOARD_WIDGET_RANGE_DAYS, referenceTs) : null;
  const start = rangeWindow?.start ?? rangeStartIso(DASHBOARD_WIDGET_RANGE_DAYS);
  const end = rangeWindow?.end;
  const maxPoints = DASHBOARD_WIDGET_MAX_POINTS;
  if (widget.family === "signal") {
    const source = widget.filters.source ?? signalDefaultSource(widget.sourceId);
    if (widget.kind === "card") {
      const latest = await getSignalLatest(widget.sourceId, source);
      if (!latest) return null;
      return {
        kind: "card",
        title: widget.title,
        metrics: signalCardKeys(widget.sourceId).map((key) => ({
          key,
          value: latest.latest_values[key],
        })),
      };
    }
    const series = await getSignalSeries(widget.sourceId, source, start, end, undefined, maxPoints);
    if (!series) return null;
    if (widget.kind === "chart") {
      return {
        kind: "chart",
        title: widget.title,
        data: series.points.map((point) => ({
          ts: point.ts,
          dvol: point.dvol,
          rvvix_14d: point.rvvix_14d,
          rvvix_30d: point.rvvix_30d,
          qvvix_30d: point.qvvix_30d,
          razor_pnl: point.razor_pnl,
          razor_vrp: point.razor_vrp,
          razor_pnl_zscore: point.razor_pnl_zscore,
          razor_vrp_zscore: point.razor_vrp_zscore,
        })),
        lines: [...signalChartLines(widget.sourceId)],
      };
    }
    const rows = signalTableRows(series);
    return {
      kind: "table",
      title: widget.title,
      columns: compactTableColumns(rows),
      rows,
    };
  }

  if (widget.family === "composite") {
    if (widget.kind === "card") {
      const latest = await getCompositeSignalLatest(widget.sourceId);
      if (!latest) return null;
      return {
        kind: "card",
        title: widget.title,
        metrics: Object.entries(latest.latest_values)
          .filter(([key]) =>
            ["sentiment_index", "directional_tilt", "fragility_index", "confidence_score"].includes(key),
          )
          .map(([key, value]) => ({ key, value })),
      };
    }
    if (widget.kind === "chart") {
      const series = await getCompositeSignalSeries(widget.sourceId, start, end, undefined, maxPoints);
      if (!series) return null;
      return {
        kind: "chart",
        title: widget.title,
        data: series.points.map((point) => ({ ts: point.ts, ...point.values })),
        lines: [
          { key: "sentiment_index", label: "Sentiment", color: "#6ac2ff", yAxisId: "left" },
          { key: "fragility_index", label: "Fragility", color: "#f58549", yAxisId: "left" },
          { key: "directional_tilt", label: "Directional", color: "#8dd3c7", yAxisId: "right" },
        ],
      };
    }
    const decomposition = await getCompositeDecomposition(widget.sourceId, start, end, undefined, maxPoints);
    if (!decomposition) return null;
    const rows = decomposition.latest_contributors.map((record) => ({
      pillar: record.pillar,
      family: record.family,
      component: record.component,
      normalized_value: record.normalized_value,
      signed_contribution: record.signed_contribution,
      quality: record.quality_flag,
    }));
    return {
      kind: "table",
      title: widget.title,
      columns: compactTableColumns(rows),
      rows,
    };
  }

  if (widget.family === "options") {
    const underlying = widget.filters.underlying ?? "BTC";
    const config = OPTIONS_DASHBOARDS.find((item) => item.id === widget.sourceId);
    if (!config) return null;
    const needsUnderlying = !["cross_asset_rv", "btc_eth_dispersion"].includes(config.id);
    if (widget.kind === "card") {
      const latest = await getOptionsDashboardLatest(widget.sourceId, needsUnderlying ? underlying : undefined);
      if (!latest) return null;
      return {
        kind: "card",
        title: widget.title,
        metrics: Object.entries(latest.latest_values).slice(0, 4).map(([key, value]) => ({ key, value })),
      };
    }
    const series = await getOptionsDashboardSeries(
      widget.sourceId,
      needsUnderlying ? underlying : undefined,
      start,
      end,
      undefined,
      maxPoints,
    );
    if (!series) return null;
    if (widget.kind === "chart") {
      return {
        kind: "chart",
        title: widget.title,
        data: series.points.map((point) => ({ ts: point.ts, ...point.values })),
        lines: config.lines,
      };
    }
    const rows = series.points.slice(-10).reverse().map((point) => ({
      ts: formatTimestamp(point.ts),
      ...point.values,
      quality: point.quality_flag,
    }));
    return {
      kind: "table",
      title: widget.title,
      columns: ["ts", ...config.tableColumns.filter((column) => column !== "ts").slice(0, 5)],
      rows,
    };
  }

  const asset = widget.filters.asset ?? "BTC";
  const venueScope = widget.filters.venue_scope ?? "all";
  const config = PERPS_DASHBOARDS.find((item) => item.id === widget.sourceId);
  if (!config) return null;
  if (widget.kind === "card") {
    const latest = await getPerpsDashboardLatest(widget.sourceId, asset, venueScope);
    if (!latest) return null;
    return {
      kind: "card",
      title: widget.title,
      metrics: Object.entries(latest.latest_values).slice(0, 4).map(([key, value]) => ({ key, value })),
    };
  }
  const series = await getPerpsDashboardSeries(widget.sourceId, asset, venueScope, start, end, undefined, maxPoints);
  if (!series) return null;
  if (widget.kind === "chart") {
    return {
      kind: "chart",
      title: widget.title,
      data: series.points.map((point) => ({ ts: point.ts, ...point.values })),
      lines: config.lines,
    };
  }
  const rows = series.points.slice(-10).reverse().map((point) => ({
    ts: formatTimestamp(point.ts),
    ...point.values,
    quality: point.quality_flag,
  }));
  return {
    kind: "table",
    title: widget.title,
    columns: ["ts", ...config.tableColumns.filter((column) => column !== "ts").slice(0, 5)],
    rows,
  };
}

function widgetSizeStyle(widget: DashboardWidget) {
  return {
    gridColumn: `span ${widget.colSpan}`,
    order: widget.order,
  } as const;
}

function widgetChartHeight(widget: DashboardWidget) {
  if (widget.kind !== "chart") {
    return 0;
  }
  if (widget.colSpan >= 12) {
    return 360;
  }
  return 300;
}

function widgetLabel(kind: DashboardWidgetKind) {
  if (kind === "card") return "card";
  if (kind === "table") return "table";
  return "chart";
}

function widgetOpenHref(widget: DashboardWidget) {
  if (widget.family === "signal") {
    return `/signals/${widget.sourceId}`;
  }
  if (widget.family === "options") {
    return `/options/${widget.sourceId}`;
  }
  if (widget.family === "perps") {
    return `/perps/${widget.sourceId}`;
  }
  const preferredCompositeDashboards: Record<string, string> = {
    market_composite: "composite_market",
    btc_composite: "composite_btc",
    eth_composite: "composite_eth",
  };
  const compositeDashboardId =
    preferredCompositeDashboards[widget.sourceId] ??
    COMPOSITE_DASHBOARDS.find((item) => item.signalId === widget.sourceId && item.id !== "composite_decomposition")?.id;
  return compositeDashboardId ? `/composite/${compositeDashboardId}` : null;
}

export function DashboardWorkspace({
  signalSources,
  compositeSources,
  optionsSources,
  perpsSources,
}: {
  signalSources: SignalSummary[];
  compositeSources: CompositeSignalSummary[];
  optionsSources: OptionsDashboardSummary[];
  perpsSources: PerpsDashboardSummary[];
}) {
  const [dashboards, setDashboards] = useState<SavedDashboard[]>([]);
  const [activeId, setActiveId] = useState<string>("main");
  const [widgetState, setWidgetState] = useState<Record<string, WidgetLoadState>>({});
  const refreshCycleRef = useRef(0);

  useEffect(() => {
    const sync = () => {
      const next = loadDashboards();
      setDashboards(next);
      setActiveId((current) => (next.some((item) => item.id === current) ? current : next[0]?.id ?? "main"));
    };
    sync();
    window.addEventListener("storage", sync);
    window.addEventListener(dashboardEventName(), sync as EventListener);
    return () => {
      window.removeEventListener("storage", sync);
      window.removeEventListener(dashboardEventName(), sync as EventListener);
    };
  }, []);

  const activeDashboard = useMemo(
    () => dashboards.find((dashboard) => dashboard.id === activeId) ?? dashboards[0] ?? null,
    [dashboards, activeId],
  );
  const signalUpdatedAtMap = useMemo(
    () => new Map(signalSources.map((source) => [source.id, source.latest_updated_at])),
    [signalSources],
  );
  const compositeUpdatedAtMap = useMemo(
    () => new Map(compositeSources.map((source) => [source.id, source.latest_updated_at])),
    [compositeSources],
  );
  const optionsUpdatedAtMap = useMemo(
    () => new Map(optionsSources.map((source) => [source.id, source.latest_updated_at])),
    [optionsSources],
  );
  const perpsUpdatedAtMap = useMemo(
    () => new Map(perpsSources.map((source) => [source.id, source.latest_updated_at])),
    [perpsSources],
  );

  const refreshWidgets = useCallback(async () => {
    if (!activeDashboard) return;
    const cycle = ++refreshCycleRef.current;
    const widgets = activeDashboard.widgets.slice().sort((a, b) => a.order - b.order);
    const activeIds = new Set(widgets.map((widget) => widget.id));

    setWidgetState((current) => {
      const next: Record<string, WidgetLoadState> = {};
      for (const widget of widgets) {
        next[widget.id] = {
          loading: true,
          payload: current[widget.id]?.payload ?? null,
        };
      }
      return next;
    });

    const worker = async (queue: DashboardWidget[]) => {
      while (queue.length > 0) {
        const widget = queue.shift();
        if (!widget) {
          return;
        }
        const referenceTs =
          widget.family === "signal"
            ? signalUpdatedAtMap.get(widget.sourceId)
            : widget.family === "composite"
              ? compositeUpdatedAtMap.get(widget.sourceId)
              : widget.family === "options"
            ? optionsUpdatedAtMap.get(widget.sourceId)
            : widget.family === "perps"
              ? perpsUpdatedAtMap.get(widget.sourceId)
              : undefined;
        const payload = await loadWidgetPayload(widget, referenceTs);
        if (refreshCycleRef.current !== cycle) {
          return;
        }
        setWidgetState((current) => {
          if (!activeIds.has(widget.id)) {
            return current;
          }
          return {
            ...current,
            [widget.id]: {
              loading: false,
              payload,
            },
          };
        });
      }
    };

    const queue = [...widgets];
    await Promise.all(
      Array.from({ length: Math.min(DASHBOARD_FETCH_CONCURRENCY, queue.length) }, () => worker(queue)),
    );
  }, [activeDashboard, compositeUpdatedAtMap, optionsUpdatedAtMap, perpsUpdatedAtMap, signalUpdatedAtMap]);

  useEffect(() => {
    void refreshWidgets();
  }, [refreshWidgets]);

  useStream((event) => {
    if (event.event === "signal.updated" || event.event === "dataset.updated" || event.event === "run.updated") {
      void refreshWidgets();
    }
  });

  const updateDashboards = useCallback((next: SavedDashboard[]) => {
    setDashboards(next);
    saveDashboards(next);
  }, []);

  const addSourceWidget = useCallback(
    (family: DashboardWidgetFamily, sourceId: string, title: string, kind: DashboardWidgetKind, filters: Record<string, string>) => {
      addWidgetToDashboards(
        {
          kind,
          family,
          sourceId,
          title: `${title} ${widgetLabel(kind)}`,
          filters,
          colSpan: kind === "card" ? 3 : 6,
          rowSpan: kind === "table" ? 2 : 1,
        },
        activeDashboard?.id,
      );
    },
    [activeDashboard?.id],
  );

  const moveWidget = useCallback((widgetId: string, direction: -1 | 1) => {
    if (!activeDashboard) return;
    const widgets = [...activeDashboard.widgets].sort((a, b) => a.order - b.order);
    const index = widgets.findIndex((item) => item.id === widgetId);
    if (index < 0) return;
    const swapIndex = index + direction;
    if (swapIndex < 0 || swapIndex >= widgets.length) return;
    const current = widgets[index];
    widgets[index] = { ...widgets[swapIndex], order: current.order };
    widgets[swapIndex] = { ...current, order: widgets[swapIndex].order };
    updateDashboards(
      dashboards.map((dashboard) =>
        dashboard.id === activeDashboard.id ? { ...dashboard, widgets } : dashboard,
      ),
    );
  }, [activeDashboard, dashboards, updateDashboards]);

  const resizeWidget = useCallback((widgetId: string) => {
    if (!activeDashboard) return;
    const next = dashboards.map((dashboard) => {
      if (dashboard.id !== activeDashboard.id) return dashboard;
      return {
        ...dashboard,
        widgets: dashboard.widgets.map((widget) => {
          if (widget.id !== widgetId) return widget;
          const nextSpan = widget.colSpan >= 12 ? 3 : widget.colSpan >= 6 ? 12 : 6;
          const nextRowSpan = widget.kind === "table" ? (widget.rowSpan >= 3 ? 2 : widget.rowSpan + 1) : widget.rowSpan;
          return { ...widget, colSpan: nextSpan, rowSpan: nextRowSpan };
        }),
      };
    });
    updateDashboards(next);
  }, [activeDashboard, dashboards, updateDashboards]);

  const removeWidget = useCallback((widgetId: string) => {
    if (!activeDashboard) return;
    updateDashboards(
      dashboards.map((dashboard) =>
        dashboard.id === activeDashboard.id
          ? { ...dashboard, widgets: dashboard.widgets.filter((widget) => widget.id !== widgetId) }
          : dashboard,
      ),
    );
  }, [activeDashboard, dashboards, updateDashboards]);

  const createNewDashboard = useCallback(() => {
    const next = [...dashboards, createDashboard(`Dashboard ${dashboards.length + 1}`)];
    updateDashboards(next);
    setActiveId(next[next.length - 1].id);
  }, [dashboards, updateDashboards]);

  const sources: SourceItem[] = useMemo(() => {
    const signalItems = signalSources.map((signal) => ({
      family: "signal" as const,
      id: signal.id,
      title: signal.name,
      subtitle: signal.description,
      filters: { source: signal.latest_source ?? signalDefaultSource(signal.id) },
    }));
    const optionsItems = optionsSources.map((item) => ({
      family: "options" as const,
      id: item.id,
      title: item.name,
      subtitle: item.description,
      filters:
        item.supported_underlyings.length > 0
          ? ({ underlying: item.supported_underlyings[0] ?? "BTC" } as Record<string, string>)
          : ({} as Record<string, string>),
    }));
    const compositeItems = compositeSources.map((signal) => ({
      family: "composite" as const,
      id: signal.id,
      title: signal.name,
      subtitle: signal.description,
      filters: {},
    }));
    const perpsItems = perpsSources.map((item) => ({
      family: "perps" as const,
      id: item.id,
      title: item.name,
      subtitle: item.description,
      filters: { asset: item.supported_assets[0] ?? "BTC", venue_scope: item.supported_venue_scopes[0] ?? "all" },
    }));
    return [...signalItems, ...compositeItems, ...optionsItems, ...perpsItems];
  }, [compositeSources, optionsSources, perpsSources, signalSources]);

  return (
    <div className="pageStack">
      <SectionHeading
        kicker="Dashboards"
        title="Custom dashboards"
        description="Compose local dashboards from Signals, Composite, Options, and Perps widgets."
      />

      <div className="panel" style={{ display: "flex", justifyContent: "space-between", gap: 12, alignItems: "center" }}>
        <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
          {dashboards.map((dashboard) => (
            <button
              key={dashboard.id}
              className={`tabItem ${dashboard.id === activeId ? "tabActive" : ""}`}
              onClick={() => setActiveId(dashboard.id)}
            >
              {dashboard.name}
            </button>
          ))}
        </div>
        <button className="tabItem" onClick={createNewDashboard}>new dashboard</button>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "minmax(280px, 340px) minmax(0, 1fr)", gap: 16, alignItems: "start" }}>
        <div className="panel" style={{ alignSelf: "start" }}>
          <div className="panelHeader">
            <h3>Widget library</h3>
            <span style={{ fontSize: 11, color: "var(--text-dim)" }}>add to {activeDashboard?.name ?? "dashboard"}</span>
          </div>
          <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            {sources.map((source) => (
              <div key={`${source.family}-${source.id}`} style={{ border: "1px solid var(--border)", borderRadius: 4, padding: 10 }}>
                <div style={{ display: "flex", justifyContent: "space-between", gap: 8, alignItems: "baseline" }}>
                  <strong style={{ fontSize: 12 }}>{source.title}</strong>
                  <span className="eyebrow">{source.family}</span>
                </div>
                <p style={{ margin: "6px 0 10px", fontSize: 12, color: "var(--text-dim)" }}>{source.subtitle}</p>
                <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
                  {(["chart", "card", "table"] as DashboardWidgetKind[]).map((kind) => (
                    <button
                      key={kind}
                      className="tabItem"
                      onClick={() => addSourceWidget(source.family, source.id, source.title, kind, source.filters)}
                    >
                      add {kind}
                    </button>
                  ))}
                </div>
              </div>
            ))}
          </div>
        </div>

        <div
          style={{
            display: "grid",
            gridTemplateColumns: "repeat(12, minmax(0, 1fr))",
            gap: 16,
            alignItems: "start",
            alignContent: "start",
            alignSelf: "start",
            gridAutoFlow: "dense",
          }}
        >
          {activeDashboard?.widgets
            .slice()
            .sort((a, b) => a.order - b.order)
            .map((widget) => {
              const state = widgetState[widget.id] ?? { loading: true, payload: null };
              const payload = state.payload;
              return (
                <div key={widget.id} className="panel" style={widgetSizeStyle(widget)}>
                  <div className="panelHeader" style={{ alignItems: "flex-start" }}>
                    <div>
                      <h3>{widget.title}</h3>
                      <span className="eyebrow">{widget.family} · {widget.kind}</span>
                    </div>
                    <div style={{ display: "flex", gap: 6, flexWrap: "wrap", justifyContent: "flex-end" }}>
                      {widgetOpenHref(widget) ? (
                        <Link className="tabItem" href={widgetOpenHref(widget) ?? "#"}>
                          open
                        </Link>
                      ) : null}
                      <button className="tabItem" onClick={() => moveWidget(widget.id, -1)}>up</button>
                      <button className="tabItem" onClick={() => moveWidget(widget.id, 1)}>down</button>
                      <button className="tabItem" onClick={() => resizeWidget(widget.id)}>resize</button>
                      <button className="tabItem" onClick={() => removeWidget(widget.id)}>remove</button>
                    </div>
                  </div>
                  {state.loading && !payload ? (
                    <div className="chartEmpty"><p className="eyebrow">Loading widget data...</p></div>
                  ) : null}
                  {payload?.kind === "chart" ? (
                    <SignalLineChart
                      data={payload.data}
                      lines={payload.lines}
                      height={widgetChartHeight(widget)}
                      loading={state.loading}
                    />
                  ) : null}
                  {payload?.kind === "card" ? (
                    <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(140px, 1fr))", gap: 12 }}>
                      {payload.metrics.map((metric) => (
                        <div key={metric.key} className="surfaceCard">
                          <div className="eyebrow">{metric.key}</div>
                          <div style={{ fontSize: 24, fontWeight: 700, color: "var(--text-primary)", marginTop: 6 }}>
                            {typeof metric.value === "number"
                              ? formatMetricValue(metric.value, metric.key)
                              : metric.value == null
                                ? "—"
                                : String(metric.value)}
                          </div>
                        </div>
                      ))}
                    </div>
                  ) : null}
                  {payload?.kind === "table" ? (
                    <DataTable columns={payload.columns} rows={payload.rows} />
                  ) : null}
                </div>
              );
            })}
          {activeDashboard && activeDashboard.widgets.length === 0 ? (
            <div className="panel" style={{ gridColumn: "1 / -1", textAlign: "center", padding: "32px 12px" }}>
              <p className="eyebrow" style={{ margin: 0 }}>No widgets yet. Add charts, cards, or tables from the library.</p>
            </div>
          ) : null}
        </div>
      </div>
    </div>
  );
}
