"use client";

import * as React from "react";

import type {
  DashboardCardCatalogItem,
  DashboardCardPrefs,
  DashboardMacroCard,
} from "@/app/customer/[tenant]/dashboard/_lib/dashboard-server-api";
import { saveDashboardCardPrefsClient } from "@/app/customer/[tenant]/dashboard/_lib/dashboard-card-prefs-api";
import { DashboardCardExcludeHint } from "@/app/customer/_components/dashboard-card-exclude-hint";
import {
  CustomerFieldsButton,
  CustomerFieldsPanel,
} from "@/app/customer/_components/customer-fields-panel";
import { SortableDashboardGrid } from "@/app/customer/_components/sortable-dashboard-grid";
import { DashboardWidgetsProvider } from "@/app/customer/_lib/dashboard-widgets-context";
import { useEnabledDashboardWidgets } from "@/app/customer/_lib/use-enabled-dashboard-widgets";
import { useDashboardCardPrefs } from "@/app/customer/_lib/use-dashboard-card-prefs";
import type { CustomerGridColumn } from "@/app/customer/_lib/customer-grid-columns";
import {
  depositInstanceLayoutId,
  isStaticWidgetLayoutId,
  topGainersInstanceLayoutId,
} from "@/app/customer/_lib/dashboard-widget-registry-definitions";
import {
  buildStaticWidgetCatalogItems,
  collectVisibleStaticWidgetIds,
  renderVisibleStaticWidgets,
} from "@/app/customer/_lib/dashboard-widget-registry-components";
import { CashflowCalendarWidget } from "@/app/customer/_components/cashflow-calendar-widget";
import { DepositWidget } from "@/app/customer/_components/deposit-widget";
import { TopGainersLosersWidget } from "@/app/customer/_components/top-gainers-losers-widget";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { cn } from "@/lib/utils";
import { RefreshCw } from "lucide-react";

function SigmaIcon({ className }: { className?: string }) {
  return (
    <svg viewBox="0 0 64 64" className={cn("size-3.5", className)} aria-hidden>
      <path
        fill="currentColor"
        d="M44.564 17.021h3.93a2.968 2.968 0 0 0 2.96-2.97v-7.09a2.966 2.966 0 0 0-2.96-2.959H21.406c-7.762-.17-11.871 9.747-6.26 15.119l11.51 11.499a1.99 1.99 0 0 1 0 2.76l-11.51 11.499c-5.605 5.361-1.508 15.296 6.26 15.119h27.088a2.966 2.966 0 0 0 2.96-2.96v-8.66a2.966 2.966 0 0 0-2.96-2.96h-3.93a2.966 2.966 0 0 0-2.96 2.96v1.77l-17.818.03L38.424 35.54a5.015 5.015 0 0 0 0-7.08L23.776 13.851h17.828a2.984 2.984 0 0 0 2.96 3.17z"
      />
    </svg>
  );
}

function MacroCardView({ card, hero = false }: { card: DashboardMacroCard; hero?: boolean }) {
  const negative = card.headline.trim().startsWith("-");

  return (
    <Card
      className={cn(
        "gap-0 border-border/60 py-0 shadow-none",
        hero ? "border-primary/20 bg-muted/20" : "h-full",
      )}
    >
      <CardContent className={cn("flex flex-col gap-1.5 px-2.5", hero ? "py-2.5" : "h-full py-2 pr-7")}>
        <div className="flex items-start gap-2">
          <div
            className={cn(
              "mt-0.5 flex shrink-0 items-center justify-center rounded-md bg-primary/10 text-primary",
              hero ? "size-7" : "size-6",
            )}
          >
            <SigmaIcon />
          </div>
          <div className="min-w-0 flex-1">
            <p
              className={cn(
                "font-semibold tabular-nums leading-tight tracking-tight",
                hero ? "text-base sm:text-lg" : "text-sm",
                negative ? "text-red-600 dark:text-red-400" : "text-foreground",
              )}
            >
              {card.headline}
            </p>
            <DashboardCardExcludeHint excludeCount={card.excludeCount} className="mt-0.5" />
            <p className={cn("mt-1 font-medium text-primary/90", hero ? "text-xs" : "text-[11px]")}>
              {card.label}
              <span className="ml-1 font-normal text-muted-foreground/80">({card.currency})</span>
            </p>
          </div>
        </div>

        <ul className="space-y-0.5 border-t border-border/50 pt-1.5">
          {card.lines.map((line) => (
            <li key={line.label} className="flex items-baseline justify-between gap-2 text-[11px]">
              <span className="truncate text-muted-foreground">{line.label}</span>
              <span className="shrink-0 tabular-nums text-foreground">{line.formatted}</span>
            </li>
          ))}
        </ul>
      </CardContent>
    </Card>
  );
}

const DEFAULT_INDIVIDUAL_CATALOG: CustomerGridColumn[] = [
  { key: "equity", label: "Equity" },
  { key: "fixedIncome", label: "Fixed Income" },
  { key: "commodity", label: "Commodity" },
  { key: "alternative", label: "Alternative Investments" },
  { key: "cash", label: "Cash" },
  { key: "total", label: "Total Value" },
];

type IndividualDashboardOverviewProps = {
  cards: DashboardMacroCard[];
  cardPrefs?: DashboardCardPrefs | null;
  cardCatalog?: DashboardCardCatalogItem[];
  tenant: string;
  loading?: boolean;
  onRefresh?: () => void;
  formattedDate: string;
};

export function IndividualDashboardOverview({
  cards,
  cardPrefs = null,
  cardCatalog,
  tenant,
  loading = false,
  onRefresh,
  formattedDate,
}: IndividualDashboardOverviewProps) {
  const [fieldsOpen, setFieldsOpen] = React.useState(false);
  const { enabled: enabledWidgets } = useEnabledDashboardWidgets(tenant);

  const cardByKey = React.useMemo(() => {
    const map = new Map<string, DashboardMacroCard>();
    for (const card of cards) map.set(card.key, card);
    return map;
  }, [cards]);

  const catalog = React.useMemo(() => {
    const available = new Set(cards.map((card) => card.key));
    const fromApi = (cardCatalog ?? []).filter(
      (item) => available.has(item.key) || isStaticWidgetLayoutId(item.key),
    );

    const macroCatalog =
      fromApi.length > 0
        ? fromApi
            .filter((item) => available.has(item.key))
            .map((item) => ({
              key: item.key,
              label: item.label,
              defaultVisible: item.defaultVisible !== false,
              group: "cards" as const,
            }))
        : cards.length > 0
          ? cards.map((card) => ({ key: card.key, label: card.label, group: "cards" as const }))
          : DEFAULT_INDIVIDUAL_CATALOG.map((item) => ({ ...item, group: "cards" as const }));

    const widgetCatalog = buildStaticWidgetCatalogItems(enabledWidgets, fromApi);
    const cashflowCatalog: CustomerGridColumn[] = Array.from(enabledWidgets.cashflowIds)
      .sort((a, b) => a - b)
      .map((id) => ({
        key: `cfw-${id}`,
        label: enabledWidgets.cashflowNames.get(id) || "Cashflow Calendar",
        defaultVisible: true,
        group: "widgets" as const,
      }));

    const topGainersCount = enabledWidgets.topGainersIds.size;
    const topGainersCatalog: CustomerGridColumn[] = Array.from(enabledWidgets.topGainersIds)
      .sort((a, b) => a - b)
      .map((id) => ({
        key: topGainersInstanceLayoutId(id, topGainersCount),
        label: enabledWidgets.topGainersNames.get(id) || "Top Gainers and Losers",
        defaultVisible: true,
        group: "widgets" as const,
      }));

    const depositCount = enabledWidgets.depositIds.size;
    const depositCatalog: CustomerGridColumn[] = Array.from(enabledWidgets.depositIds)
      .sort((a, b) => a - b)
      .map((id) => ({
        key: depositInstanceLayoutId(id, depositCount),
        label: enabledWidgets.depositNames.get(id) || "Deposit",
        defaultVisible: true,
        group: "widgets" as const,
      }));

    return [...macroCatalog, ...widgetCatalog, ...cashflowCatalog, ...topGainersCatalog, ...depositCatalog];
  }, [cardCatalog, cards, enabledWidgets]);

  const savePrefs = React.useCallback(
    async (prefs: { visibility: Record<string, boolean>; order: string[] }) => {
      await saveDashboardCardPrefsClient(prefs, "individual", tenant);
    },
    [tenant],
  );

  const {
    visibility,
    order,
    visibleOrderedKeys,
    hideAll,
    setCardVisible,
    reorderShown,
  } = useDashboardCardPrefs({
    catalog,
    initialPrefs: cardPrefs,
    lockedKeys: ["total"],
    savePrefs,
  });

  const shownMacroKeys = visibleOrderedKeys.filter((key) => cardByKey.has(key));
  const heroKey = shownMacroKeys.includes("total") ? "total" : shownMacroKeys[0];
  const gridKeys = shownMacroKeys.filter((key) => key !== heroKey);
  const heroCard = heroKey ? cardByKey.get(heroKey) : undefined;

  const widgetIds = React.useMemo(() => {
    // Cashflow / Top Gainers / Deposit instances fetch individually (skipBatch) — exclude from batch.
    return collectVisibleStaticWidgetIds(enabledWidgets, visibility);
  }, [enabledWidgets, visibility]);

  const cashflowWidgets = React.useMemo(
    () =>
      Array.from(enabledWidgets.cashflowIds)
        .sort((a, b) => a - b)
        .filter((id) => visibility[`cfw-${id}`] !== false)
        .map((id) => (
          <div key={`cfw-${id}`} className="lg:col-span-2">
            <CashflowCalendarWidget
              widgetId={id}
              layoutId={`cfw-${id}`}
              title={enabledWidgets.cashflowNames.get(id) || "Cashflow Calendar"}
            />
          </div>
        )),
    [enabledWidgets, visibility],
  );

  const topGainersWidgets = React.useMemo(
    () =>
      Array.from(enabledWidgets.topGainersIds)
        .sort((a, b) => a - b)
        .filter((id) => {
          const layoutId = topGainersInstanceLayoutId(id, enabledWidgets.topGainersIds.size);
          return visibility[layoutId] !== false;
        })
        .map((id) => {
          const layoutId = topGainersInstanceLayoutId(id, enabledWidgets.topGainersIds.size);
          return (
            <div key={layoutId} className="lg:col-span-2">
              <TopGainersLosersWidget
                widgetId={id}
                layoutId={layoutId}
                title={enabledWidgets.topGainersNames.get(id) || "Top Gainers and Losers"}
              />
            </div>
          );
        }),
    [enabledWidgets, visibility],
  );

  const depositWidgets = React.useMemo(
    () =>
      Array.from(enabledWidgets.depositIds)
        .sort((a, b) => a - b)
        .filter((id) => {
          const layoutId = depositInstanceLayoutId(id, enabledWidgets.depositIds.size);
          return visibility[layoutId] !== false;
        })
        .map((id) => {
          const layoutId = depositInstanceLayoutId(id, enabledWidgets.depositIds.size);
          return (
            <div key={layoutId} className="lg:col-span-2">
              <DepositWidget
                widgetId={id}
                layoutId={layoutId}
                title={enabledWidgets.depositNames.get(id) || "Deposit"}
              />
            </div>
          );
        }),
    [enabledWidgets, visibility],
  );

  return (
    <DashboardWidgetsProvider tenant={tenant} widgetIds={widgetIds}>
      <div className="flex flex-col gap-2">
        <div className="flex min-w-0 items-center justify-between gap-3">
          <div className="flex min-w-0 flex-wrap items-baseline gap-x-3 gap-y-0.5">
            <h1 className="text-3xl tracking-tight">Dashboard</h1>
            <p className="truncate text-sm text-muted-foreground">{formattedDate}</p>
          </div>
          <div className="flex shrink-0 items-center gap-2">
            <CustomerFieldsButton label="Customize" showLabel onClick={() => setFieldsOpen(true)} />
            {onRefresh ? (
              <Button size="sm" variant="outline" onClick={onRefresh} disabled={loading}>
                <RefreshCw className={cn("size-3.5", loading && "animate-spin")} />
                Refresh
              </Button>
            ) : null}
          </div>
          <CustomerFieldsPanel
            open={fieldsOpen}
            onOpenChange={setFieldsOpen}
            catalog={catalog}
            visibility={visibility}
            order={order}
            lockedKeys={["total"]}
            title="Cards & Widgets"
            onToggle={setCardVisible}
            onReorder={reorderShown}
            onHideAll={hideAll}
          />
        </div>

        {heroCard ? <MacroCardView card={heroCard} hero /> : null}

        <SortableDashboardGrid
          items={gridKeys}
          onReorder={reorderShown}
          className="grid grid-cols-2 gap-1.5 sm:grid-cols-3 xl:grid-cols-5"
        >
          {(key) => {
            const card = cardByKey.get(key);
            if (!card) return null;
            return <MacroCardView card={card} />;
          }}
        </SortableDashboardGrid>

        {widgetIds.length > 0 ? (
          <div className="mt-4 grid gap-4 lg:grid-cols-2">
            {renderVisibleStaticWidgets(enabledWidgets, visibility, { wrapIndividual: true })}
          {cashflowWidgets}
          {topGainersWidgets}
            {depositWidgets}
          </div>
        ) : null}
      </div>
    </DashboardWidgetsProvider>
  );
}
