"use client";

import { useRef, useLayoutEffect } from "react";
import { createRoot, type Root } from "react-dom/client";
import { GridStack } from "gridstack";
import type { WidgetItem, DashboardAllocation } from "@/types/dashboard";
import { AllocationStateView } from "./AllocationStateView";
import { UsdEurWidget } from "./UsdEurWidget";
import { TickTapeWidget } from "./TickTapeWidget";
import { MarketOverviewFxWidget } from "./MarketOverviewFxWidget";
import { MarketOverviewIndicesWidget } from "./MarketOverviewIndicesWidget";
import { MarketOverviewStocksWidget } from "./MarketOverviewStocksWidget";
import { WatchlistWidget } from "./WatchlistWidget";
import { CashHoldingSummaryWidget } from "./CashHoldingSummaryWidget";
import { PastPerformanceWidget } from "./PastPerformanceWidget";
import { DepositSummaryWidget } from "./DepositSummaryWidget";

const WIDGET_CARD_CHART_HEIGHT = 260;
const WIDGET_CARD_PLACEHOLDER_HEIGHT = 180;

function normalizeWidgetFilePath(filePath: string): string {
  return filePath
    .trim()
    .toLowerCase()
    .replace(/[\s-]+/g, "_");
}

function getWidgetKind(filePath: string):
  | "asset_allocation"
  | "widget6"
  | "ticktape"
  | "market_overview_fx"
  | "market_overview_indices"
  | "market_overview_stocks"
  | "watchlist"
  | "cash_holding"
  | "past_performance"
  | "deposit"
  | "unknown" {
  const normalized = normalizeWidgetFilePath(filePath);
  if (normalized === "asset_allocation") return "asset_allocation";
  if (normalized === "widget6") return "widget6";
  if (normalized === "ticktape") return "ticktape";
  if (["market_overview_fx", "marketoverview_fx", "market_overview_forex"].includes(normalized)) {
    return "market_overview_fx";
  }
  if (
    ["market_overview_indices", "marketoverview_indices", "market_overview_index"].includes(
      normalized
    )
  ) {
    return "market_overview_indices";
  }
  if (["market_overview_stocks", "marketoverview_stocks", "market_overview_equities"].includes(normalized)) {
    return "market_overview_stocks";
  }
  if (normalized === "watchlist") return "watchlist";
  if (["cash_holding", "cash_holding_summary", "cash_holdings"].includes(normalized)) {
    return "cash_holding";
  }
  if (normalized === "past_performance") return "past_performance";
  if (["deposit", "deposits", "deposit_summary", "deposit_widget"].includes(normalized)) {
    return "deposit";
  }
  return "unknown";
}

// Map file_path → accent color dot
const WIDGET_ACCENT: Record<string, string> = {
  asset_allocation:        "bg-violet-500",
  widget6:                 "bg-emerald-500",
  ticktape:                "bg-sky-500",
  market_overview_fx:      "bg-amber-500",
  market_overview_indices: "bg-rose-500",
  market_overview_stocks:  "bg-blue-500",
  watchlist:               "bg-teal-500",
  cash_holding:            "bg-orange-500",
  past_performance:        "bg-indigo-500",
  deposit:                 "bg-cyan-500",
};

export interface WidgetCardContentProps {
  widget: WidgetItem;
  allocation: DashboardAllocation;
  currency?: string;
  piePalette: string[];
}

export function WidgetCardContent({
  widget,
  allocation,
  currency,
  piePalette,
}: WidgetCardContentProps) {
  const widgetKind = getWidgetKind(widget.file_path);
  const isAssetAllocation = widgetKind === "asset_allocation";
  const displayTitle = isAssetAllocation ? "Asset Allocation" : widget.name || "Widget";
  const accent = WIDGET_ACCENT[widgetKind] ?? "bg-slate-400";

  return (
    <div className="flex h-full flex-col overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm transition-shadow duration-200 hover:shadow-md">
      {/* Title bar */}
      <div className="flex items-center gap-2.5 border-b border-slate-100 bg-white px-4 py-3 shrink-0">
        <span className={`h-2 w-2 shrink-0 rounded-full ${accent}`} />
        <p className="text-sm font-semibold text-slate-800 truncate">{displayTitle}</p>
      </div>

      {/* Content */}
      <div className="flex-1 min-h-0 overflow-hidden">
        {isAssetAllocation ? (
          <AllocationStateView
            allocation={allocation}
            currency={currency}
            piePalette={piePalette}
            height={WIDGET_CARD_CHART_HEIGHT}
            widget={widget}
            placeholderMinHeight={WIDGET_CARD_PLACEHOLDER_HEIGHT}
          />
        ) : widgetKind === "widget6" ? (
          <UsdEurWidget height={WIDGET_CARD_CHART_HEIGHT} />
        ) : widgetKind === "ticktape" ? (
          <TickTapeWidget />
        ) : widgetKind === "market_overview_fx" ? (
          <MarketOverviewFxWidget height={WIDGET_CARD_CHART_HEIGHT} />
        ) : widgetKind === "market_overview_indices" ? (
          <MarketOverviewIndicesWidget height={WIDGET_CARD_CHART_HEIGHT} />
        ) : widgetKind === "market_overview_stocks" ? (
          <MarketOverviewStocksWidget height={WIDGET_CARD_CHART_HEIGHT} />
        ) : widgetKind === "watchlist" ? (
          <WatchlistWidget height={WIDGET_CARD_CHART_HEIGHT} />
        ) : widgetKind === "cash_holding" ? (
          <CashHoldingSummaryWidget height={WIDGET_CARD_CHART_HEIGHT} />
        ) : widgetKind === "past_performance" ? (
          <PastPerformanceWidget height={WIDGET_CARD_CHART_HEIGHT} />
        ) : widgetKind === "deposit" ? (
          <DepositSummaryWidget height={WIDGET_CARD_CHART_HEIGHT} />
        ) : (
          <div className="flex h-full min-h-[180px] flex-col items-center justify-center px-4 text-center">
            <p className="text-sm font-semibold text-slate-700">{widget.name}</p>
            <p className="mt-1 text-xs text-slate-400">
              {widget.short_description || "Active widget"}
            </p>
          </div>
        )}
      </div>
    </div>
  );
}

export interface GridWidgetItemProps {
  widget: WidgetItem;
  allocation: DashboardAllocation;
  currency?: string;
  piePalette: string[];
  layout: { x: number; y: number; w: number; h: number };
  grid: GridStack | null;
}

export function GridWidgetItem({
  widget,
  allocation,
  currency,
  piePalette,
  layout,
  grid,
}: GridWidgetItemProps) {
  const elRef = useRef<HTMLDivElement>(null);
  const contentRef = useRef<HTMLElement | null>(null);
  const rootRef = useRef<Root | null>(null);
  const layoutRef = useRef(layout);
  layoutRef.current = layout;

  useLayoutEffect(() => {
    const el = elRef.current;
    if (!el || !grid) return;

    const { x, y, w, h } = layoutRef.current;
    grid.makeWidget(el, { id: widget.widget_id, x, y, w, h });

    const contentEl = el.querySelector(".grid-stack-item-content") as HTMLElement | null;
    if (contentEl) {
      contentRef.current = contentEl;
      if (!rootRef.current) {
        rootRef.current = createRoot(contentEl);
        rootRef.current.render(
          <WidgetCardContent
            widget={widget}
            allocation={allocation}
            currency={currency}
            piePalette={piePalette}
          />
        );
      }
    }

    return () => {
      const root = rootRef.current;
      const content = contentRef.current;
      rootRef.current = null;
      contentRef.current = null;

      try {
        grid.removeWidget(el, false);
      } catch {
        // ignore
      }

      if (root && content) {
        queueMicrotask(() => {
          try {
            root.unmount();
          } catch {
            // ignore
          }
        });
      }
    };
  }, [grid, widget.widget_id]);

  useLayoutEffect(() => {
    if (!rootRef.current) return;
    rootRef.current.render(
      <WidgetCardContent
        widget={widget}
        allocation={allocation}
        currency={currency}
        piePalette={piePalette}
      />
    );
  }, [widget, allocation, currency, piePalette]);

  return (
    <div
      ref={elRef}
      className="grid-stack-item"
      data-widget-id={widget.widget_id}
      gs-id={widget.widget_id}
      gs-w={layout.w}
      gs-h={layout.h}
      gs-x={layout.x}
      gs-y={layout.y}
    >
      <div className="grid-stack-item-content" />
    </div>
  );
}
