"use client";

import * as React from "react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { RefreshCw, Settings2 } from "lucide-react";

import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { cn } from "@/lib/utils";
import { customerUrl } from "@/lib/tenant";

import { DashboardWidgetBody } from "@/app/customer/_components/dashboard-charts/dashboard-widget-body";
import { ResponsiveHorizontalBarChart } from "@/app/customer/_components/dashboard-charts/responsive-horizontal-bar-chart";
import { PortfolioScopeWidgetHint } from "@/app/customer/_components/portfolio-scope-widget-hint";
import { useWidgetSettingsAction } from "@/app/customer/_components/dashboard-widget-configure-provider";
import type { WidgetLayoutTier } from "@/app/customer/_lib/use-widget-container-size";
import { LAYOUT_IDS } from "@/app/customer/_lib/dashboard-layout";
import { useBatchedWidgetLoader } from "@/app/customer/_lib/use-batched-widget-loader";
import { useDashboardWidgetConfigRefresh } from "@/app/customer/_lib/use-dashboard-widget-config-refresh";
import { useCustomerPortalSession } from "@/app/customer/_components/customer-portal-session-context";
import { configureParamForWidget } from "@/app/customer/[tenant]/settings/_components/widget-config";
import { buildTopGainersLosersBars } from "@/app/customer/[tenant]/reports/top-gainers-losers/_lib/top-gainers-losers-chart-data";
import { fetchTopGainersLosersWidgetClient } from "@/app/customer/[tenant]/reports/top-gainers-losers/_lib/top-gainers-losers-api";
import type {
  TopGainersLosersAmountField,
  TopGainersLosersBucket,
  TopGainersLosersBucketTotals,
  TopGainersLosersInstrumentRow,
  TopGainersLosersSubclientRow,
  TopGainersLosersWidgetData,
} from "@/app/customer/[tenant]/reports/top-gainers-losers/_lib/top-gainers-losers-types";
import {
  ConsolidatedIndividualDialog,
  type ConsolidatedIndividualTarget,
} from "@/app/customer/[tenant]/reports/consolidated-holdings-report/_components/consolidated-holdings-report/consolidated-individual-dialog";
import { isCorporateParentPortalUser } from "@/lib/frontend-auth/report-capabilities";

type RankingMode = "instrument" | "subclient";

function instrumentTypeLabel(row: TopGainersLosersInstrumentRow): string {
  return row.product_type?.trim() || row.asset_type_title?.trim() || "—";
}

type TopGainersLosersWidgetProps = {
  widgetId?: number;
  layoutId?: string;
  title?: string;
};

function segmentClass(active: boolean) {
  return cn(
    "rounded-md px-3 py-1.5 text-xs font-medium transition-colors",
    active
      ? "bg-background text-primary shadow-sm"
      : "text-muted-foreground hover:text-foreground",
  );
}

function periodLabel(period: TopGainersLosersWidgetData["period"] | undefined): string {
  switch (period) {
    case "1w":
      return "1 Week";
    case "1m":
      return "1 Month";
    case "3m":
      return "3 Months";
    case "6m":
      return "6 Months";
    case "1y":
      return "1 Year";
    default:
      return "1 Day";
  }
}

function amountClass(raw: number) {
  if (!Number.isFinite(raw) || Math.abs(raw) < 1e-9) return "text-foreground";
  return raw < 0 ? "text-red-600 dark:text-red-400" : "text-emerald-700 dark:text-emerald-400";
}

function formatTotalAmount(raw: number): string {
  return raw.toLocaleString("en-US", {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  });
}

function RankingEmptyState({ label }: { label: string }) {
  return (
    <div className="flex min-h-[7.5rem] flex-1 items-center justify-center rounded-lg border border-dashed border-border/70 bg-background/40 px-3 py-6">
      <p className="text-center text-xs text-muted-foreground">{label}</p>
    </div>
  );
}

function InstrumentNameIsinCell({
  row,
  onIsinClick,
}: {
  row: TopGainersLosersInstrumentRow;
  onIsinClick?: (row: TopGainersLosersInstrumentRow) => void;
}) {
  const name = row.name?.trim() || row.isin || row.ticker || "—";
  const isin = row.isin?.trim() || row.ticker?.trim() || null;
  const canOpenDetail = Boolean(onIsinClick && isin);

  return (
    <div className="min-w-0">
      <p className="truncate font-medium" title={name}>
        {name}
      </p>
      {isin ? (
        canOpenDetail ? (
          <button
            type="button"
            className="mt-0.5 block max-w-full truncate font-mono text-[10px] text-foreground/65 underline-offset-2 hover:text-primary hover:underline"
            title={isin}
            onClick={() => onIsinClick?.(row)}
          >
            {isin}
          </button>
        ) : (
          <p className="mt-0.5 truncate font-mono text-[10px] text-foreground/65" title={isin}>
            {isin}
          </p>
        )
      ) : null}
    </div>
  );
}

function SubclientNameCell({ name }: { name: string }) {
  return (
    <div className="min-w-0">
      <p className="truncate font-medium" title={name}>
        {name}
      </p>
    </div>
  );
}

function fallbackBucketTotals(
  rows: Array<{ value: TopGainersLosersAmountField; difference_rc: TopGainersLosersAmountField }>,
): TopGainersLosersBucketTotals {
  const totalMarketValue = rows.reduce((sum, row) => sum + row.value.raw, 0);
  const totalPnl = rows.reduce((sum, row) => sum + row.difference_rc.raw, 0);
  return {
    value: { raw: totalMarketValue, fmt: formatTotalAmount(totalMarketValue) },
    difference_rc: { raw: totalPnl, fmt: formatTotalAmount(totalPnl) },
  };
}

function RankingTable({
  bucket,
  mode,
  currency,
  compact = false,
  onInstrumentIsinClick,
}: {
  bucket: TopGainersLosersBucket<TopGainersLosersInstrumentRow | TopGainersLosersSubclientRow>;
  mode: RankingMode;
  currency: string;
  compact?: boolean;
  onInstrumentIsinClick?: (row: TopGainersLosersInstrumentRow) => void;
}) {
  const rows = bucket.items;
  const others = bucket.others ?? null;
  const totals = bucket.totals ?? fallbackBucketTotals(rows);
  const labelColSpan = mode === "instrument" ? 2 : 1;

  if (rows.length === 0) {
    return null;
  }

  return (
    <div className="overflow-x-auto rounded-lg border border-border/60 bg-background/60 [-ms-overflow-style:none] [scrollbar-width:thin] [&::-webkit-scrollbar]:h-1.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-border/80 [&::-webkit-scrollbar-track]:bg-transparent">
      <table
        className={cn("w-full text-left text-xs", mode === "instrument" ? "min-w-[640px]" : "min-w-[520px]")}
      >
        {!compact ? (
          <thead className="sticky top-0 z-10 border-b border-border/50 bg-muted/70 text-[10px] font-semibold uppercase tracking-wide text-foreground/70 backdrop-blur-sm">
            <tr>
              <th className="min-w-[9rem] px-3 py-2.5">Name</th>
              {mode === "instrument" ? (
                <th className="min-w-[5rem] max-w-[7rem] px-3 py-2.5">Type</th>
              ) : null}
              <th className="w-[4.75rem] min-w-[4.75rem] px-3 py-2.5 text-right">P&amp;L %</th>
              <th className="w-[8rem] min-w-[8rem] px-3 py-2.5 text-right">Mkt Value ({currency})</th>
              <th className="w-[7.5rem] min-w-[7.5rem] px-3 py-2.5 text-right">P&amp;L ({currency})</th>
            </tr>
          </thead>
        ) : null}
        <tbody className="divide-y divide-border/50">
          {rows.map((row, index) => {
            const instrumentRow = mode === "instrument" ? (row as TopGainersLosersInstrumentRow) : null;
            const subclientRow = mode === "subclient" ? (row as TopGainersLosersSubclientRow) : null;
            const name =
              mode === "subclient"
                ? subclientRow?.customer_name?.trim() ||
                  (subclientRow?.customer_id != null ? `Client ${subclientRow.customer_id}` : "—")
                : instrumentRow?.name || instrumentRow?.isin || instrumentRow?.ticker || "—";
            const rowKey =
              mode === "instrument"
                ? `${instrumentRow?.isin ?? instrumentRow?.ticker ?? "instrument"}-${index}`
                : `${name}-${index}`;
            const pct = row.gain_lose_percentage;
            const marketValue = row.value as TopGainersLosersAmountField;
            const amount = row.difference_rc as TopGainersLosersAmountField;

            return (
              <tr key={rowKey} className="transition-colors hover:bg-muted/30">
                <td className="min-w-0 max-w-[12rem] px-3 py-2.5">
                  {mode === "instrument" && instrumentRow ? (
                    <InstrumentNameIsinCell row={instrumentRow} onIsinClick={onInstrumentIsinClick} />
                  ) : (
                    <SubclientNameCell name={name} />
                  )}
                </td>
                {mode === "instrument" ? (
                  <td
                    className="min-w-0 max-w-[7rem] truncate px-3 py-2.5 text-foreground/70"
                    title={instrumentRow ? instrumentTypeLabel(instrumentRow) : undefined}
                  >
                    {instrumentRow ? instrumentTypeLabel(instrumentRow) : "—"}
                  </td>
                ) : null}
                <td
                  className={cn(
                    "w-[4.75rem] min-w-[4.75rem] whitespace-nowrap px-3 py-2.5 text-right tabular-nums",
                    pct ? amountClass(pct.raw) : "text-muted-foreground",
                  )}
                >
                  {pct?.fmt ?? "—"}
                </td>
                {!compact ? (
                  <>
                    <td className="w-[8rem] min-w-[8rem] whitespace-nowrap px-3 py-2.5 text-right tabular-nums text-foreground">
                      {marketValue.fmt}
                    </td>
                    <td
                      className={cn(
                        "w-[7.5rem] min-w-[7.5rem] whitespace-nowrap px-3 py-2.5 text-right tabular-nums",
                        amountClass(amount.raw),
                      )}
                    >
                      {amount.fmt}
                    </td>
                  </>
                ) : null}
              </tr>
            );
          })}
          {!compact && others ? (
            <tr className="bg-muted/10 text-foreground/70">
              <td className="min-w-0 max-w-[12rem] px-3 py-2.5">
                <p className="truncate font-medium italic" title="Others">
                  Others
                </p>
              </td>
              {mode === "instrument" ? <td className="px-3 py-2.5">—</td> : null}
              <td className="w-[4.75rem] min-w-[4.75rem] whitespace-nowrap px-3 py-2.5 text-right tabular-nums">
                —
              </td>
              <td className="w-[8rem] min-w-[8rem] whitespace-nowrap px-3 py-2.5 text-right tabular-nums">
                {others.value.fmt}
              </td>
              <td
                className={cn(
                  "w-[7.5rem] min-w-[7.5rem] whitespace-nowrap px-3 py-2.5 text-right tabular-nums",
                  amountClass(others.difference_rc.raw),
                )}
              >
                {others.difference_rc.fmt}
              </td>
            </tr>
          ) : null}
        </tbody>
        {!compact ? (
          <tfoot>
            <tr className="border-t-2 border-border/70 bg-muted/25 font-semibold">
              <td colSpan={labelColSpan} className="px-3 py-2.5">
                Total
              </td>
              <td className="w-[4.75rem] min-w-[4.75rem] whitespace-nowrap px-3 py-2.5 text-right text-muted-foreground">
                —
              </td>
              <td className="w-[8rem] min-w-[8rem] whitespace-nowrap px-3 py-2.5 text-right tabular-nums">
                {totals.value.fmt}
              </td>
              <td
                className={cn(
                  "w-[7.5rem] min-w-[7.5rem] whitespace-nowrap px-3 py-2.5 text-right tabular-nums",
                  amountClass(totals.difference_rc.raw),
                )}
              >
                {totals.difference_rc.fmt}
              </td>
            </tr>
          </tfoot>
        ) : null}
      </table>
    </div>
  );
}

function CompactRankingsList({
  rows,
  mode,
  onInstrumentIsinClick,
}: {
  rows: TopGainersLosersInstrumentRow[] | TopGainersLosersSubclientRow[];
  mode: RankingMode;
  onInstrumentIsinClick?: (row: TopGainersLosersInstrumentRow) => void;
}) {
  if (rows.length === 0) {
    return null;
  }

  return (
    <div className="divide-y divide-border/50 overflow-hidden rounded-lg border border-border/60 bg-background/60">
      {rows.slice(0, 5).map((row, index) => {
        const instrumentRow = mode === "instrument" ? (row as TopGainersLosersInstrumentRow) : null;
        const subclientRow = mode === "subclient" ? (row as TopGainersLosersSubclientRow) : null;
        const name =
          mode === "subclient"
            ? subclientRow?.customer_name?.trim() ||
              (subclientRow?.customer_id != null ? `Client ${subclientRow.customer_id}` : "—")
            : instrumentRow?.name || instrumentRow?.isin || instrumentRow?.ticker || "—";
        const pct = row.gain_lose_percentage;
        const rowKey =
          mode === "instrument"
            ? `${instrumentRow?.isin ?? instrumentRow?.ticker ?? "instrument"}-${index}`
            : `${name}-${index}`;

        return (
          <div key={rowKey} className="flex items-center justify-between gap-2 px-3 py-2.5 text-xs">
            <div className="min-w-0 flex-1">
              {mode === "instrument" && instrumentRow ? (
                <InstrumentNameIsinCell row={instrumentRow} onIsinClick={onInstrumentIsinClick} />
              ) : (
                <SubclientNameCell name={name} />
              )}
            </div>
            <span
              className={cn(
                "shrink-0 font-medium tabular-nums",
                pct ? amountClass(pct.raw) : "text-muted-foreground",
              )}
            >
              {pct?.fmt ?? "—"}
            </span>
          </div>
        );
      })}
    </div>
  );
}

function RankingSidePanel({
  title,
  emptyLabel,
  variant,
  bars,
  chartHeight,
  showChart,
  showFullTables,
  bucket,
  compactRows,
  mode,
  currency,
  onInstrumentIsinClick,
}: {
  title: string;
  emptyLabel: string;
  variant: "gainers" | "losers";
  bars: ReturnType<typeof buildTopGainersLosersBars>;
  chartHeight: number;
  showChart: boolean;
  showFullTables: boolean;
  bucket: TopGainersLosersBucket<TopGainersLosersInstrumentRow | TopGainersLosersSubclientRow>;
  compactRows: TopGainersLosersInstrumentRow[] | TopGainersLosersSubclientRow[];
  mode: RankingMode;
  currency: string;
  onInstrumentIsinClick?: (row: TopGainersLosersInstrumentRow) => void;
}) {
  const isEmpty = bucket.items.length === 0;

  return (
    <section
      className={cn(
        "flex min-w-0 flex-col gap-3 rounded-xl border p-3",
        variant === "gainers"
          ? "border-emerald-500/25 bg-emerald-500/[0.04]"
          : "border-rose-500/25 bg-rose-500/[0.04]",
      )}
    >
      <h3
        className={cn(
          "text-[11px] font-semibold uppercase tracking-[0.08em]",
          variant === "gainers" ? "text-emerald-700 dark:text-emerald-400" : "text-rose-700 dark:text-rose-400",
        )}
      >
        {title}
      </h3>

      {isEmpty ? (
        <RankingEmptyState label={emptyLabel} />
      ) : (
        <>
          {showChart && bars.length > 0 ? (
            <div className="rounded-lg border border-border/50 bg-background/50 p-2.5">
              <ResponsiveHorizontalBarChart items={bars} height={chartHeight} barSize={14} />
            </div>
          ) : null}
          {showFullTables ? (
            <RankingTable
              bucket={bucket}
              mode={mode}
              currency={currency}
              onInstrumentIsinClick={onInstrumentIsinClick}
            />
          ) : (
            <CompactRankingsList
              rows={compactRows}
              mode={mode}
              onInstrumentIsinClick={onInstrumentIsinClick}
            />
          )}
        </>
      )}
    </section>
  );
}

function RankingsPanel({
  data,
  mode,
  currency,
  tier,
  onInstrumentIsinClick,
}: {
  data: TopGainersLosersWidgetData;
  mode: RankingMode;
  currency: string;
  tier: WidgetLayoutTier;
  onInstrumentIsinClick?: (row: TopGainersLosersInstrumentRow) => void;
}) {
  const section = mode === "instrument" ? data.by_instrument : data.by_subclient;
  const gainerBars = React.useMemo(
    () => buildTopGainersLosersBars(section.top_gainers.items, mode, "gainers"),
    [section.top_gainers.items, mode],
  );
  const loserBars = React.useMemo(
    () => buildTopGainersLosersBars(section.top_losers.items, mode, "losers"),
    [section.top_losers.items, mode],
  );

  const chartHeight = tier === "expanded" ? 140 : 120;
  const showFullTables = tier === "expanded";
  const showChart = tier !== "compact";
  const compactLimit = tier === "compact" ? 3 : 5;
  const isinClick = mode === "instrument" ? onInstrumentIsinClick : undefined;

  return (
    <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
      <RankingSidePanel
        title="Top Gainers"
        emptyLabel="No gainers in this view"
        variant="gainers"
        bars={gainerBars}
        chartHeight={chartHeight}
        showChart={showChart}
        showFullTables={showFullTables}
        bucket={section.top_gainers}
        compactRows={section.top_gainers.items.slice(0, compactLimit)}
        mode={mode}
        currency={currency}
        onInstrumentIsinClick={isinClick}
      />
      <RankingSidePanel
        title="Top Losers"
        emptyLabel="No losers in this view"
        variant="losers"
        bars={loserBars}
        chartHeight={chartHeight}
        showChart={showChart}
        showFullTables={showFullTables}
        bucket={section.top_losers}
        compactRows={section.top_losers.items.slice(0, compactLimit)}
        mode={mode}
        currency={currency}
        onInstrumentIsinClick={isinClick}
      />
    </div>
  );
}

function hasRankings(data: TopGainersLosersWidgetData, includeSubclient: boolean): boolean {
  const hasInstrumentRankings =
    data.by_instrument.top_gainers.items.length > 0 || data.by_instrument.top_losers.items.length > 0;

  if (!includeSubclient) {
    return hasInstrumentRankings;
  }

  return (
    hasInstrumentRankings ||
    data.by_subclient.top_gainers.items.length > 0 ||
    data.by_subclient.top_losers.items.length > 0
  );
}

function AssetClassChipStrip({
  assetClasses,
  value,
  onValueChange,
}: {
  assetClasses: TopGainersLosersWidgetData["asset_classes"];
  value: string;
  onValueChange: (value: string) => void;
}) {
  if (assetClasses.length === 0) return null;

  const chips = [{ code: "all", label: "All" }, ...assetClasses];

  return (
    <div className="min-w-0 flex-1 overflow-x-auto [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden">
      <div className="flex w-max items-center gap-1.5">
        {chips.map((chip) => {
          const selected = value === chip.code;
          return (
            <button
              key={chip.code}
              type="button"
              onClick={() => onValueChange(chip.code)}
              className={cn(
                "shrink-0 rounded-full border px-2.5 py-1 text-xs font-medium transition-colors",
                selected
                  ? "border-primary bg-primary text-primary-foreground shadow-sm"
                  : "border-transparent bg-muted/70 text-muted-foreground hover:bg-muted hover:text-foreground",
              )}
            >
              {chip.label}
            </button>
          );
        })}
      </div>
    </div>
  );
}

export function TopGainersLosersWidget({
  widgetId,
  layoutId,
  title = "Top Gainers and Losers",
}: TopGainersLosersWidgetProps) {
  const params = useParams<{ tenant: string }>();
  const tenant = params?.tenant ?? "";
  const { user } = useCustomerPortalSession();
  const showClientTab = isCorporateParentPortalUser(user);
  const [assetClass, setAssetClass] = React.useState("all");
  const [rankingMode, setRankingMode] = React.useState<RankingMode>("instrument");
  const resolvedLayoutId = layoutId ?? LAYOUT_IDS.topGainersLosers;
  const skipBatch = resolvedLayoutId !== LAYOUT_IDS.topGainersLosers || assetClass !== "all";

  const fetchIndividual = React.useCallback(async () => {
    const result = await fetchTopGainersLosersWidgetClient(
      tenant,
      assetClass === "all" ? undefined : assetClass,
      widgetId,
    );
    return { data: result.data, errorMessage: result.errorMessage };
  }, [tenant, assetClass, widgetId]);

  const { data, loading, refreshing, error, refresh } = useBatchedWidgetLoader<TopGainersLosersWidgetData>({
    layoutId: resolvedLayoutId,
    fetchIndividual,
    skipBatch,
  });

  useDashboardWidgetConfigRefresh(widgetId, refresh);

  const [individualOpen, setIndividualOpen] = React.useState(false);
  const [individualTarget, setIndividualTarget] = React.useState<ConsolidatedIndividualTarget | null>(null);

  const handleInstrumentIsinClick = React.useCallback((row: TopGainersLosersInstrumentRow) => {
    const isin = row.isin?.trim() || row.ticker?.trim();
    if (!isin) return;

    setIndividualTarget({
      isin,
      assetType: row.asset_type_title ?? "",
      assetClass: row.asset_class_code ?? "",
      name: row.name ?? undefined,
    });
    setIndividualOpen(true);
  }, []);

  const currency = data?.currency ?? "USD";
  const selectedPeriodLabel = periodLabel(data?.period);
  const assetClasses = data?.asset_classes ?? [];
  const showInitialSkeleton = loading && !data;
  const showRankings = data ? hasRankings(data, showClientTab) : false;
  const settingsHrefFallback =
    widgetId && widgetId > 0
      ? customerUrl(tenant, `/settings?section=dashboard&configure=${configureParamForWidget("tgl", widgetId)}`)
      : customerUrl(tenant, "/settings?section=dashboard");
  const { settingsHref, onSettingsClick } = useWidgetSettingsAction(widgetId ?? 0, settingsHrefFallback);

  React.useEffect(() => {
    if (assetClass === "all") return;
    if (assetClasses.some((item) => item.code === assetClass)) return;
    setAssetClass("all");
  }, [assetClass, assetClasses]);

  return (
    <>
      <Card className="flex h-full flex-col gap-0 overflow-hidden py-0 shadow-sm">
        <CardHeader className="flex flex-row items-start justify-between gap-3 space-y-0 border-b py-3">
          <div className="min-w-0 flex-1">
            <CardTitle className="text-base text-primary">{title}</CardTitle>
            <p className="flex min-w-0 items-center gap-1.5 truncate text-[10px] text-muted-foreground">
              <span className="shrink-0">Reporting currency: {currency}</span>
              <PortfolioScopeWidgetHint inline />
            </p>
          </div>
          <div className="flex items-center gap-2 shrink-0">
            <span className="rounded-full border border-border/60 bg-muted/40 px-2.5 py-1 text-[10px] font-medium uppercase tracking-wide text-muted-foreground">
              {selectedPeriodLabel}
            </span>
            {onSettingsClick ? (
              <Button
                type="button"
                variant="outline"
                size="icon"
                className="size-8 shrink-0"
                title="Configure widget"
                onClick={onSettingsClick}
              >
                <Settings2 className="size-4" />
                <span className="sr-only">Configure</span>
              </Button>
            ) : settingsHref ? (
              <Button asChild variant="outline" size="icon" className="size-8 shrink-0">
                <Link href={settingsHref} title="Configure widget">
                  <Settings2 className="size-4" />
                  <span className="sr-only">Configure</span>
                </Link>
              </Button>
            ) : null}
            <Button
              variant="ghost"
              size="icon"
              className="size-8 shrink-0"
              disabled={refreshing}
              onClick={() => void refresh()}
              title="Refresh"
            >
              <RefreshCw className={cn("size-3.5", refreshing && "animate-spin")} />
              <span className="sr-only">Refresh</span>
            </Button>
          </div>
        </CardHeader>

        {showInitialSkeleton ? (
          <CardContent className="flex flex-1 flex-col gap-3 p-4">
            <Skeleton className="h-8 w-48" />
            <Skeleton className="h-40 w-full" />
          </CardContent>
        ) : error && !data ? (
          <CardContent className="flex flex-1 flex-col items-center justify-center gap-3 p-6 text-center">
            <p className="text-muted-foreground text-sm">{error}</p>
            <Button variant="outline" size="sm" onClick={() => void refresh()}>
              Try again
            </Button>
          </CardContent>
        ) : data ? (
          <CardContent className="relative flex min-h-0 flex-1 flex-col overflow-hidden p-0">
            {refreshing ? (
              <div
                className="absolute inset-0 z-10 flex items-center justify-center bg-background/60 backdrop-blur-[1px]"
                aria-busy="true"
                aria-live="polite"
              >
                <RefreshCw className="size-6 animate-spin text-muted-foreground" />
              </div>
            ) : null}
            <DashboardWidgetBody className="overflow-y-auto p-4">
              {({ tier }) => (
                <div className={cn("flex flex-col gap-4", refreshing && "opacity-70")}>
                  <div className="flex flex-col gap-2.5 sm:flex-row sm:items-center sm:justify-between">
                    <AssetClassChipStrip
                      assetClasses={assetClasses}
                      value={assetClass}
                      onValueChange={setAssetClass}
                    />
                    {showClientTab ? (
                      <div
                        className="inline-flex w-fit shrink-0 gap-0.5 self-start rounded-lg border border-border/60 bg-muted/40 p-1 sm:self-auto"
                        role="tablist"
                        aria-label="Ranking mode"
                      >
                        <button
                          type="button"
                          role="tab"
                          aria-selected={rankingMode === "instrument"}
                          className={segmentClass(rankingMode === "instrument")}
                          onClick={() => setRankingMode("instrument")}
                        >
                          By Instrument
                        </button>
                        <button
                          type="button"
                          role="tab"
                          aria-selected={rankingMode === "subclient"}
                          className={segmentClass(rankingMode === "subclient")}
                          onClick={() => setRankingMode("subclient")}
                        >
                          By Client
                        </button>
                      </div>
                    ) : null}
                  </div>

                  {showRankings ? (
                    <RankingsPanel
                      data={data}
                      mode={showClientTab ? rankingMode : "instrument"}
                      currency={currency}
                      tier={tier}
                      onInstrumentIsinClick={handleInstrumentIsinClick}
                    />
                  ) : (
                    <p className="py-8 text-center text-sm text-muted-foreground">
                      No gainers or losers found in your portfolio.
                    </p>
                  )}
                </div>
              )}
            </DashboardWidgetBody>
          </CardContent>
        ) : (
          <CardContent className="flex flex-1 items-center justify-center p-6 text-center">
            <p className="text-muted-foreground text-sm">No gainers or losers found in your portfolio.</p>
          </CardContent>
        )}
      </Card>
      <ConsolidatedIndividualDialog
        open={individualOpen}
        onOpenChange={setIndividualOpen}
        target={individualTarget}
      />
    </>
  );
}
