"use client";

import * as React from "react";

import { useRenderEffect } from "@/hooks/use-changed";
import { format } from "date-fns";
import {
  ChevronsDownUp,
  ChevronsUpDown,
  ChevronRight,
  RefreshCw,
} from "lucide-react";

import {
  CustomerFieldsButton,
  CustomerFieldsPanel,
} from "@/app/customer/_components/customer-fields-panel";
import { useImpersonationScopeRefresh } from "@/app/customer/_lib/admin/use-impersonation-scope-refresh";
import type { CustomerColumnPrefs } from "@/app/customer/_lib/customer-grid-columns";
import { useCustomerTableColumnPrefs } from "@/app/customer/_lib/use-customer-table-column-prefs";
import { resolveCustomerTenant } from "@/app/customer/_lib/resolve-customer-tenant";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { FRONTEND_ROUTES } from "@/config/frontend-routes";
import { formatQuantityFixed, parseBackendNumberOrNull } from "@/lib/format/numbers";
import { errorMessageOr } from "@/lib/toast-api-error";
import { cn } from "@/lib/utils";

import {
  DELIVERED_HOLDINGS_COLUMNS,
  DELIVERED_HOLDINGS_LOCKED_KEYS,
  readDeliveredHoldingsColumnPrefs,
  resolveDeliveredHoldingsVisibleColumns,
  saveDeliveredHoldingsColumnPrefs,
  type DeliveredHoldingsColumnDef,
  type DeliveredHoldingsColumnKey,
} from "../_lib/delivered-holdings-history-columns";
import type {
  DeliveredHoldingsEvent,
  DeliveredHoldingsHistoryData,
  DeliveredHoldingsPosition,
  DeliveredHoldingsProductFilter,
  DeliveredHoldingsSettlementFilter,
  DeliveredHoldingsUnderlying,
  DeliveredHoldingsVerdictFilter,
} from "../_lib/delivered-holdings-history-types";

import { DeliveredHoldingsHistorySkeleton } from "./delivered-holdings-history-skeleton";
import { buildUnderlyingBreakEven } from "../_lib/underlying-break-even";
import {
  buildPortfolioIsinOptions,
  mergePortfolioIsinOptions,
  PortfolioIsinCombobox,
  type PortfolioIsinOption,
} from "./portfolio-isin-combobox";

const EMPTY_DELIVERED_EVENTS: DeliveredHoldingsEvent[] = [];

type IsinGroup = {
  key: string;
  isin: string;
  name: string;
  positions: DeliveredHoldingsPosition[];
  watchCount: number;
  okCount: number;
  expiredCount: number;
  potentialCount: number;
  liveCount: number;
  deliveryCount: number;
  earlyCount: number;
  interestCount: number;
  products: string[];
  clientCount: number;
  totalShares: number;
  totalInterest: number;
};

function formatDisplayDate(value: string): string {
  const ts = Date.parse(value);
  if (Number.isNaN(ts)) return value || "—";
  return format(new Date(ts), "dd MMM yyyy");
}

function formatNum(value: unknown, digits = 2): string {
  if (value === null || value === undefined || value === "") return "—";
  const n = parseBackendNumberOrNull(value);
  if (n === null) return "—";
  return formatQuantityFixed(n, digits);
}

function yesNo(value: boolean | undefined): string {
  return value ? "Yes" : "No";
}

function verdictClass(group: string | undefined): string {
  if (group === "watch") return "border-transparent bg-rose-600/15 text-rose-800 dark:text-rose-300";
  if (group === "ok") return "border-transparent bg-emerald-600/15 text-emerald-800 dark:text-emerald-300";
  if (group === "expired") return "border-transparent bg-indigo-600/15 text-indigo-800 dark:text-indigo-300";
  if (group === "potential") return "border-transparent bg-amber-600/15 text-amber-900 dark:text-amber-300";
  if (group === "live") return "border-transparent bg-slate-600/15 text-slate-800 dark:text-slate-300";
  return "border-transparent bg-muted text-muted-foreground";
}

/** User-facing names for outcome tabs / chips (API keys stay watch|ok|expired|potential|live). */
function verdictGroupLabel(group: string | undefined): string {
  if (group === "watch") return "Needs review";
  if (group === "ok") return "Received";
  if (group === "expired") return "Expired";
  if (group === "potential") return "On Potential";
  if (group === "live") return "Live";
  return group || "—";
}

function productClass(product: string): string {
  if (/^accu$/i.test(product)) return "bg-emerald-600/15 text-emerald-800 dark:text-emerald-300";
  if (/^decu$/i.test(product)) return "bg-rose-600/15 text-rose-800 dark:text-rose-300";
  if (/structure/i.test(product)) return "bg-violet-600/15 text-violet-800 dark:text-violet-300";
  return "bg-muted text-muted-foreground";
}

/** Same segment control as Structure / Accu reports. */
function segmentClass(active: boolean) {
  return cn(
    "h-8 shrink-0 rounded-md px-3 font-semibold text-xs transition-colors",
    active
      ? "bg-emerald-600 text-white shadow-sm"
      : "text-muted-foreground hover:bg-background/80 hover:text-foreground",
  );
}

function positionIsin(pos: DeliveredHoldingsPosition): string {
  return String(pos.isin || pos.underlying_isin || "").trim().toUpperCase() || "—";
}

function positionName(pos: DeliveredHoldingsPosition): string {
  const name = String(
    pos.structure_name || pos.name || pos.underlying_name || pos.ticker || "",
  ).trim();
  const isin = positionIsin(pos);
  if (name && name.toUpperCase() !== isin) return name;
  return "";
}

function positionProductType(pos: DeliveredHoldingsPosition): string {
  return String(pos.product_type || "").trim();
}

function positionUnderlyings(pos: DeliveredHoldingsPosition): DeliveredHoldingsUnderlying[] {
  if (Array.isArray(pos.underlyings) && pos.underlyings.length > 0) {
    return pos.underlyings;
  }
  const name = String(pos.underlying_name || pos.name || "").trim();
  const isin = String(pos.underlying_isin || pos.ticker || "").trim();
  if (!name && !isin) return [];
  return [{ name: name || isin, isin, ticker: isin, delivered: Boolean(pos.delivery) }];
}

/** Master coupon coverage + ledger cash (hover = Master dates ✓/✗). */
function interestCouponTooltip(pos: DeliveredHoldingsPosition): string | undefined {
  const coupons = Array.isArray(pos.interest_coupons) ? pos.interest_coupons : [];
  const expected = Number(pos.coupon_expected ?? coupons.length) || coupons.length;
  const matched = Number(pos.coupon_received ?? 0) || 0;
  const prior = Number(pos.coupon_prior ?? 0) || 0;
  const priorEst = Number(pos.interest_prior_estimate ?? 0) || 0;
  const ledgerAmt = Number(pos.interest_amount ?? 0) || 0;
  const header = pos.coupon_complete
    ? `Master coupons complete (${matched}/${expected})`
    : `Master coupons ${matched}/${expected}`;
  const parts = [header];
  if (ledgerAmt > 0) {
    parts.push(`Ledger cash listed: ${formatNum(ledgerAmt, 2)}`);
  }
  if (prior > 0) {
    parts.push(
      priorEst > 0
        ? `Prior (no cash line): ${prior} period(s) · ~${formatNum(priorEst, 2)} estimated`
        : `Prior (no cash line): ${prior} period(s)`,
    );
  }
  if (pos.interest_gap_note) parts.push(String(pos.interest_gap_note));
  if (coupons.length === 0) {
    return parts.length > 1 || pos.verdict_note ? parts.join("\n") : pos.verdict_note || undefined;
  }
  const lines = coupons.map((c) => {
    const date = String(c.date || "").trim() || "—";
    if (!c.received) return `✗ ${date}`;
    return c.ledger === false ? `✓ ${date} (schedule only — no cash line)` : `✓ ${date} (ledger)`;
  });
  return [...parts, ...lines].join("\n");
}

function interestCellLabel(pos: DeliveredHoldingsPosition): React.ReactNode {
  const hasInterest = Boolean(pos.interest_received) || Number(pos.interest_amount ?? 0) > 0;
  const expected = Number(pos.coupon_expected ?? 0) || 0;
  const matched = Number(pos.coupon_received ?? 0) || 0;
  const prior = Number(pos.coupon_prior ?? 0) || 0;
  const amount = pos.interest_amount ? formatNum(pos.interest_amount, 2) : "";
  const priorEst =
    Number(pos.interest_prior_estimate ?? 0) > 0
      ? formatNum(pos.interest_prior_estimate, 2)
      : "";

  if (!hasInterest && expected <= 0) {
    return "No";
  }

  return (
    <span className="inline-flex max-w-[220px] flex-col gap-0.5 leading-tight">
      <span className="whitespace-nowrap">
        {hasInterest ? "Yes" : "No"}
        {expected > 0 ? (
          <span
            className={cn(
              "ml-1 tabular-nums text-xs",
              pos.coupon_complete
                ? "text-emerald-800 dark:text-emerald-300"
                : "text-amber-800 dark:text-amber-300",
            )}
          >
            {matched}/{expected}
            {pos.coupon_complete ? " ✓" : ""}
          </span>
        ) : null}
        {amount ? (
          <span className="ml-1 text-muted-foreground text-xs tabular-nums">{amount}</span>
        ) : null}
      </span>
      {prior > 0 ? (
        <span className="text-[10px] text-amber-800 dark:text-amber-300">
          +prior ~{priorEst || "—"} ({prior} sch.)
        </span>
      ) : null}
    </span>
  );
}

function normalizeSearchNeedle(raw: string): string {
  return raw.replace(/\s+/g, "").trim().toUpperCase();
}

function legMatchesSearch(leg: DeliveredHoldingsUnderlying, needle: string): boolean {
  if (!needle) return false;
  for (const value of [leg.isin, leg.ticker, leg.name]) {
    const compact = normalizeSearchNeedle(String(value || ""));
    if (compact !== "" && compact.includes(needle)) return true;
  }
  return false;
}

/** Split "Display Name [subdomain]" from ListingUsers labels. */
function parseClientLabel(raw: string): { name: string; handle: string } {
  const value = raw.trim();
  if (!value) return { name: "—", handle: "" };
  const match = value.match(/^(.*?)\s*\[([^\]]+)\]\s*$/);
  if (!match) return { name: value, handle: "" };
  const name = match[1]?.trim() || value;
  const handle = match[2]?.trim() || "";
  return { name, handle };
}

function ClientCell({ pos }: { pos: DeliveredHoldingsPosition }) {
  const raw = String(pos.client_label || pos.user_label || "").trim();
  const { name, handle } = parseClientLabel(raw);
  return (
    <div className="min-w-0" title={raw || undefined}>
      <div className="truncate leading-snug">{name}</div>
      {handle ? (
        <span className="mt-0.5 inline-block max-w-full truncate rounded-full bg-muted px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground">
          {handle}
        </span>
      ) : null}
    </div>
  );
}

function renderDeliveredHoldingsCell(
  column: DeliveredHoldingsColumnDef,
  pos: DeliveredHoldingsPosition,
  searchNeedle = "",
): React.ReactNode {
  switch (column.key as DeliveredHoldingsColumnKey) {
    case "rm":
      return pos.rm_label || "—";
    case "client":
      return <ClientCell pos={pos} />;
    case "structure":
      return <StructureDetailCell pos={pos} searchNeedle={searchNeedle} />;
    case "outcome":
      return (
        <Badge
          variant="secondary"
          className={cn("font-medium text-[10px]", verdictClass(pos.verdict_group))}
          title={pos.verdict_note}
        >
          {pos.verdict_label || pos.verdict_group || "—"}
        </Badge>
      );
    case "delivery":
      return yesNo(pos.delivery);
    case "early":
      return yesNo(pos.early_delivery);
    case "interest":
      return interestCellLabel(pos);
    case "shares":
      return formatNum(pos.delivered_qty ?? pos.total_delivered_qty, 2);
    case "note":
      return pos.verdict_note || pos.potential_reason || "—";
    case "fvd":
      return pos.fvd ? formatDisplayDate(pos.fvd) : "—";
    case "uid":
      return String(pos.uid || "").trim() || "—";
    default:
      return "—";
  }
}

/** Product type badges + one underlying name per line (ISINs on hover). */
function StructureDetailCell({
  pos,
  searchNeedle = "",
}: {
  pos: DeliveredHoldingsPosition;
  searchNeedle?: string;
}) {
  const product = String(pos.product_label || pos.product_family || "").trim();
  const productType = positionProductType(pos);
  const underlyings = positionUnderlyings(pos);
  const tooltipParts = underlyings.map((leg) => {
    const legName = String(leg.name || "").trim();
    const legIsin = String(leg.isin || leg.ticker || "").trim();
    const mark = leg.delivered ? " · delivered" : "";
    if (legName && legIsin && legName.toUpperCase() !== legIsin.toUpperCase()) {
      return `${legName} (${legIsin})${mark}`;
    }
    return `${legName || legIsin || "—"}${mark}`;
  });

  return (
    <div className="min-w-0" title={tooltipParts.join("\n") || undefined}>
      <div className="flex flex-wrap items-center gap-1">
        <Badge
          variant="secondary"
          className={cn("border-transparent font-medium text-[10px]", productClass(product))}
        >
          {product || "—"}
        </Badge>
        {productType && productType.toLowerCase() !== product.toLowerCase() ? (
          <Badge variant="outline" className="font-medium text-[10px]">
            {productType}
          </Badge>
        ) : null}
      </div>
      {underlyings.length > 0 ? (
        <div className="mt-1 space-y-0.5 text-[11px] leading-snug text-muted-foreground">
          {underlyings.map((leg, index) => {
            const legName = String(leg.name || leg.isin || leg.ticker || "—").trim();
            const legIsin = String(leg.isin || leg.ticker || "").trim();
            const hit = legMatchesSearch(leg, searchNeedle);
            return (
              <div
                key={`${legIsin || legName}-${index}`}
                className={cn(
                  "break-words",
                  leg.delivered && "font-medium text-emerald-800 dark:text-emerald-300",
                  hit &&
                    "rounded bg-amber-100 px-0.5 text-amber-950 dark:bg-amber-900/40 dark:text-amber-100",
                )}
              >
                {legName}
                {leg.delivered ? " ✓" : ""}
              </div>
            );
          })}
        </div>
      ) : null}
    </div>
  );
}

function groupByIsin(positions: DeliveredHoldingsPosition[]): IsinGroup[] {
  const map = new Map<string, IsinGroup>();
  const productSets = new Map<string, Set<string>>();
  const clientSets = new Map<string, Set<string>>();

  for (const pos of positions) {
    const isin = positionIsin(pos);
    const key = isin !== "—" ? isin : `pk:${pos.position_key}`;
    let group = map.get(key);
    if (!group) {
      group = {
        key,
        isin,
        name: positionName(pos),
        positions: [],
        watchCount: 0,
        okCount: 0,
        expiredCount: 0,
        potentialCount: 0,
        liveCount: 0,
        deliveryCount: 0,
        earlyCount: 0,
        interestCount: 0,
        products: [],
        clientCount: 0,
        totalShares: 0,
        totalInterest: 0,
      };
      map.set(key, group);
      productSets.set(key, new Set());
      clientSets.set(key, new Set());
    }
    if (!group.name) group.name = positionName(pos);
    group.positions.push(pos);

    if (pos.verdict_group === "watch") group.watchCount += 1;
    else if (pos.verdict_group === "ok") group.okCount += 1;
    else if (pos.verdict_group === "expired") group.expiredCount += 1;
    else if (pos.verdict_group === "potential") group.potentialCount += 1;
    else if (pos.verdict_group === "live") group.liveCount += 1;
    if (pos.delivery) group.deliveryCount += 1;
    if (pos.early_delivery) group.earlyCount += 1;
    if (pos.interest_received) group.interestCount += 1;
    group.totalShares += Number(pos.delivered_qty ?? pos.total_delivered_qty ?? 0) || 0;
    group.totalInterest += Number(pos.interest_amount ?? pos.total_interest_dividend ?? 0) || 0;

    const product = String(pos.product_label || pos.product_family || "").trim();
    // Interest is evidence on the parent Structure/Accu — never a separate product chip.
    if (product && !/^interest/i.test(product)) {
      productSets.get(key)?.add(product);
    }
    const client = String(pos.client_label || pos.user_label || "").trim();
    if (client) clientSets.get(key)?.add(client);
  }

  const groups = Array.from(map.values());
  for (const group of groups) {
    group.products = Array.from(productSets.get(group.key) ?? []);
    group.clientCount = (clientSets.get(group.key) ?? new Set()).size;
  }
  groups.sort((a, b) => {
    if (b.watchCount !== a.watchCount) return b.watchCount - a.watchCount;
    return (a.name || a.isin).localeCompare(b.name || b.isin);
  });
  return groups;
}

function EventEvidence({
  events,
  position,
}: {
  events: DeliveredHoldingsEvent[];
  position?: DeliveredHoldingsPosition;
}) {
  const cashEvents = events.filter(
    (event) =>
      event.event_kind === "interest_dividend" ||
      /interest|dividend/i.test(String(event.received_type ?? "")),
  );
  const ledgerCash = cashEvents.reduce((sum, event) => sum + (Number(event.amount) || 0), 0);
  const prior = Number(position?.coupon_prior ?? 0) || 0;
  const priorEst = Number(position?.interest_prior_estimate ?? 0) || 0;
  const expected = Number(position?.coupon_expected ?? 0) || 0;
  const matched = Number(position?.coupon_received ?? 0) || 0;
  const gapNote = String(position?.interest_gap_note || "").trim();
  const showGap = prior > 0 && expected > 0;

  if (events.length === 0 && !showGap) {
    return (
      <p className="px-4 py-2.5 text-muted-foreground text-xs">No event detail in this date range.</p>
    );
  }

  return (
    <div className="mx-3 my-2 space-y-0 overflow-hidden rounded-lg border border-border/60 bg-card">
      <div className="flex items-center gap-2 border-b border-border/60 bg-muted/40 px-3 py-1.5">
        <span className="font-semibold text-[10px] uppercase tracking-wide text-muted-foreground">
          Cash & delivery events
        </span>
        {events.length > 0 ? (
          <span className="text-[10px] text-muted-foreground tabular-nums">
            {events.length} row{events.length === 1 ? "" : "s"}
          </span>
        ) : null}
      </div>
      {showGap ? (
        <div
          className="border-b border-border/60 bg-muted/30 px-3 py-1.5 text-[11px] leading-snug text-muted-foreground"
          title={gapNote || undefined}
        >
          Master {matched}/{expected}
          {position?.coupon_complete ? " ✓" : ""} · cash{" "}
          {formatNum(ledgerCash || position?.interest_amount, 2)} ({cashEvents.length}) · prior ~
          {formatNum(priorEst, 2)} ({prior} schedule-only — no cash rows)
        </div>
      ) : null}
      {events.length === 0 ? (
        <p className="px-3 py-2 text-muted-foreground text-xs">No ledger cash/delivery events listed.</p>
      ) : (
        <Table className="min-w-[640px]">
          <TableHeader>
            <TableRow className="bg-muted/20 hover:bg-muted/20">
              <TableHead className="h-7 px-3 text-[11px] font-medium">Date</TableHead>
              <TableHead className="h-7 px-3 text-[11px] font-medium">Event</TableHead>
              <TableHead className="h-7 px-3 text-[11px] font-medium">Underlying</TableHead>
              <TableHead className="h-7 px-3 text-right text-[11px] font-medium">Value</TableHead>
              <TableHead className="h-7 px-3 text-[11px] font-medium">Detail</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {events.map((event, index) => {
              const isCash =
                event.event_kind === "interest_dividend" ||
                /interest|dividend/i.test(String(event.received_type ?? ""));
              const label = isCash
                ? "Cash received"
                : event.event_kind === "structure_delivery"
                  ? "Shares delivered"
                  : event.event_kind === "option_deliver"
                    ? "Option"
                    : "Shares delivered";
              const value = isCash
                ? formatNum(event.amount, 2)
                : event.delivered_qty != null
                  ? `${formatNum(event.delivered_qty, 2)} sh`
                  : "—";
              const undName = String(event.underlying_name || "").trim();
              const undIsin = String(event.underlying_isin || event.ticker || "").trim();
              const showUndIsin =
                undIsin !== "" &&
                undName !== "" &&
                undName.toUpperCase() !== undIsin.toUpperCase() &&
                !isCash;
              return (
                <TableRow
                  key={`${event.event_id ?? "e"}-${index}`}
                  className={cn(index % 2 === 0 ? "bg-muted/5" : undefined)}
                >
                  <TableCell className="whitespace-nowrap px-3 py-1.5 text-xs tabular-nums">
                    {formatDisplayDate(event.event_date)}
                  </TableCell>
                  <TableCell className="px-3 py-1.5 text-xs">
                    <Badge
                      variant="secondary"
                      className={cn(
                        "h-5 border-transparent px-1.5 font-medium text-[10px]",
                        isCash
                          ? "bg-emerald-600/15 text-emerald-800 dark:text-emerald-300"
                          : "bg-muted text-foreground/80",
                      )}
                    >
                      {label}
                    </Badge>
                  </TableCell>
                  <TableCell className="px-3 py-1.5 text-xs">
                    {isCash ? (
                      <span className="text-muted-foreground">—</span>
                    ) : (
                      <div>
                        <div>{undName || undIsin || "—"}</div>
                        {showUndIsin ? (
                          <div className="font-mono text-[10px] text-muted-foreground">{undIsin}</div>
                        ) : null}
                      </div>
                    )}
                  </TableCell>
                  <TableCell className="px-3 py-1.5 text-right font-medium tabular-nums text-xs">
                    {value}
                  </TableCell>
                  <TableCell className="px-3 py-1.5 text-muted-foreground text-xs">
                    {event.delivered_label || "—"}
                  </TableCell>
                </TableRow>
              );
            })}
            {showGap && priorEst > 0 ? (
              <TableRow className="border-t bg-muted/30 hover:bg-muted/30">
                <TableCell className="whitespace-nowrap px-3 py-1.5 text-xs text-muted-foreground">
                  Prior
                </TableCell>
                <TableCell className="px-3 py-1.5 text-xs">Prior interest (estimate)</TableCell>
                <TableCell className="px-3 py-1.5 text-xs text-muted-foreground">—</TableCell>
                <TableCell className="px-3 py-1.5 text-right tabular-nums text-xs">
                  ~{formatNum(priorEst, 2)}
                </TableCell>
                <TableCell className="px-3 py-1.5 text-muted-foreground text-xs">
                  {prior} Master period{prior === 1 ? "" : "s"} — schedule ✓ only, no cash line
                </TableCell>
              </TableRow>
            ) : null}
          </TableBody>
        </Table>
      )}
    </div>
  );
}

export function DeliveredHoldingsHistoryView() {
  const [product, setProduct] = React.useState<DeliveredHoldingsProductFilter>("structure");
  const [verdict, setVerdict] = React.useState<DeliveredHoldingsVerdictFilter>("all");
  const [settlement, setSettlement] =
    React.useState<DeliveredHoldingsSettlementFilter>("all");
  const [isin, setIsin] = React.useState("");
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState<string | null>(null);
  const [data, setData] = React.useState<DeliveredHoldingsHistoryData | null>(null);
  const [scopeRefreshKey, setScopeRefreshKey] = React.useState(0);
  const [openKeys, setOpenKeys] = React.useState<Set<string>>(() => new Set());
  const [expandedRow, setExpandedRow] = React.useState<string | null>(null);
  const [fieldsOpen, setFieldsOpen] = React.useState(false);
  const [columnPrefs, setColumnPrefs] = React.useState<CustomerColumnPrefs | null>(null);
  const [portfolioIsinOptions, setPortfolioIsinOptions] = React.useState<PortfolioIsinOption[]>(
    [],
  );
  const abortRef = React.useRef<AbortController | null>(null);

  React.useEffect(() => {
    // Browser storage can only be read after hydration, so this cannot be a lazy initial state.
    // eslint-disable-next-line react-hooks/set-state-in-effect
    setColumnPrefs(readDeliveredHoldingsColumnPrefs());
  }, []);

  const saveColumnPrefs = React.useCallback(async (prefs: CustomerColumnPrefs) => {
    await saveDeliveredHoldingsColumnPrefs(prefs);
    setColumnPrefs(prefs);
  }, []);

  const {
    columnVisibility,
    columnOrder,
    hideAll,
    setColumnVisible,
    reorderShown,
  } = useCustomerTableColumnPrefs({
    catalog: DELIVERED_HOLDINGS_COLUMNS,
    initialPrefs: columnPrefs,
    lockedKeys: DELIVERED_HOLDINGS_LOCKED_KEYS,
    savePrefs: saveColumnPrefs,
  });

  const visibleColumns = React.useMemo(
    () =>
      resolveDeliveredHoldingsVisibleColumns(
        columnOrder,
        columnVisibility as Record<string, boolean>,
      ),
    [columnOrder, columnVisibility],
  );

  const refreshForScope = React.useCallback(() => {
    setPortfolioIsinOptions([]);
    setIsin("");
    setScopeRefreshKey((value) => value + 1);
  }, []);
  useImpersonationScopeRefresh(refreshForScope);

  const load = React.useCallback(
    async (
      productFilter: DeliveredHoldingsProductFilter,
      verdictFilter: DeliveredHoldingsVerdictFilter,
      settlementFilter: DeliveredHoldingsSettlementFilter,
      isinFilter: string,
    ) => {
      abortRef.current?.abort();
      const controller = new AbortController();
      abortRef.current = controller;

      const tenant = resolveCustomerTenant();
      setLoading(true);
      setError(null);
      try {
        const params = new URLSearchParams({
          product: productFilter,
          verdict: verdictFilter,
          settlement: settlementFilter,
        });
        const isinValue = isinFilter.trim();
        if (isinValue !== "") params.set("isin", isinValue);
        const response = await fetch(
          `${FRONTEND_ROUTES.customerPortal.deliveredHoldingsHistory.list(tenant)}?${params}`,
          {
            method: "GET",
            credentials: "same-origin",
            headers: { Accept: "application/json" },
            cache: "no-store",
            signal: controller.signal,
          },
        );
        const payload = (await response.json().catch(() => null)) as {
          status?: string;
          message?: string;
          data?: DeliveredHoldingsHistoryData;
        } | null;
        if (!response.ok || payload?.status !== "success" || !payload.data) {
          throw new Error(payload?.message?.trim() || "Could not load scorecard.");
        }
        if (controller.signal.aborted) return;
        setData(payload.data);
        setExpandedRow(null);
      } catch (e) {
        if (controller.signal.aborted) return;
        setData(null);
        setError(errorMessageOr(e, "Could not load scorecard."));
      } finally {
        if (abortRef.current === controller) {
          setLoading(false);
        }
      }
    },
    [],
  );

  React.useEffect(() => {
    // Fetch kickoff: the loader raises its own loading flag first (fetch-in-effect).
    // eslint-disable-next-line react-hooks/set-state-in-effect
    void load(product, verdict, settlement, isin);
  }, [load, product, verdict, settlement, isin, scopeRefreshKey]);

  React.useEffect(() => {
    return () => {
      abortRef.current?.abort();
    };
  }, []);

  const applyPortfolioIsin = (nextIsin: string) => {
    const next = normalizeSearchNeedle(nextIsin);
    setIsin(next);
    // Full delivery map for an ISIN spans Structure / Accu / Option.
    if (next !== "") {
      setProduct("all");
      setVerdict("all");
      setSettlement("all");
    }
  };

  const clearSearch = () => {
    setIsin("");
  };

  const positions = React.useMemo(() => data?.positions ?? [], [data?.positions]);
  const events = data?.events ?? EMPTY_DELIVERED_EVENTS;
  const totals = data?.totals ?? {};
  const groups = React.useMemo(() => groupByIsin(positions), [positions]);
  const searchNeedle = normalizeSearchNeedle(isin);

  useRenderEffect([positions], () => {
    if (positions.length === 0) return;
    setPortfolioIsinOptions((previous) =>
      mergePortfolioIsinOptions(previous, buildPortfolioIsinOptions(positions)),
    );
  });

  const searchSummary = React.useMemo(() => {
    if (!searchNeedle || positions.length === 0) return null;
    const clients = new Set<string>();
    let deliveredHoldings = 0;
    let totalShares = 0;
    let deliveredLegs = 0;
    for (const pos of positions) {
      const client = String(pos.client_label || pos.user_label || "").trim();
      if (client) clients.add(client);
      if (pos.delivery) {
        deliveredHoldings += 1;
        totalShares += Number(pos.delivered_qty ?? pos.total_delivered_qty ?? 0) || 0;
      }
      for (const leg of positionUnderlyings(pos)) {
        if (legMatchesSearch(leg, searchNeedle) && leg.delivered) deliveredLegs += 1;
      }
    }
    return {
      holdings: positions.length,
      structures: groups.length,
      clients: clients.size,
      deliveredHoldings,
      deliveredLegs,
      totalShares,
    };
  }, [searchNeedle, positions, groups.length]);

  const underlyingBreakEven = React.useMemo(() => {
    if (!searchNeedle || positions.length === 0) return null;
    const matchedDeliveredUnderlying = positions.some((pos) =>
      positionUnderlyings(pos).some(
        (leg) => leg.delivered && legMatchesSearch(leg, searchNeedle),
      ),
    );
    // Only when the search targets a delivered underlying (e.g. Netflix), not the product ISIN.
    if (!matchedDeliveredUnderlying) return null;
    return buildUnderlyingBreakEven(positions, searchNeedle);
  }, [searchNeedle, positions]);

  useRenderEffect([groups, searchNeedle], () => {
    if (groups.length === 0) return;
    // Search: expand every matching ISIN group so the delivery map is visible.
    if (searchNeedle !== "") {
      setOpenKeys(new Set(groups.map((g) => g.key)));
      return;
    }
    setOpenKeys(new Set(groups.filter((g) => g.watchCount > 0).map((g) => g.key)));
  });

  const allGroupsOpen =
    groups.length > 0 && groups.every((group) => openKeys.has(group.key));

  const expandAllGroups = () => {
    setOpenKeys(new Set(groups.map((group) => group.key)));
  };

  const collapseAllGroups = () => {
    setOpenKeys(new Set());
    setExpandedRow(null);
  };

  const toggleExpandCollapseAll = () => {
    if (allGroupsOpen) collapseAllGroups();
    else expandAllGroups();
  };

  const eventsByPosition = React.useMemo(() => {
    const map = new Map<string, DeliveredHoldingsEvent[]>();
    for (const event of events) {
      const key = String(event.position_key ?? "");
      if (!key) continue;
      const list = map.get(key) ?? [];
      list.push(event);
      map.set(key, list);
    }
    return map;
  }, [events]);

  const toggleGroup = (key: string) => {
    setOpenKeys((prev) => {
      const next = new Set(prev);
      if (next.has(key)) next.delete(key);
      else next.add(key);
      return next;
    });
  };

  return (
    <div className="flex min-w-0 flex-col gap-3">
      <div className="flex w-full min-w-0 shrink-0 flex-col gap-4 border-b pb-3 sm:flex-row sm:items-start">
        <div className="min-w-0 shrink-0 space-y-2">
          <div>
            <h1 className="font-semibold text-2xl tracking-tight">Delivered Holdings History</h1>
            <p className="text-muted-foreground text-sm">
              Search a structure or delivered equity ISIN to map every holding and share lot.
              {loading ? " Loading…" : ""}
            </p>
          </div>
          <div className="flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center">
            <div
              className="inline-flex flex-wrap gap-0.5 rounded-lg border border-border/60 bg-muted/40 p-1"
              role="tablist"
              aria-label="Product"
            >
              {(
                [
                  ["all", `All products (${totals.product_all ?? 0})`],
                  ["structure", `Structure (${totals.structure ?? 0})`],
                  ["accu", `Accu / Decu (${totals.accu ?? 0})`],
                  ["option", `Option (${totals.option ?? 0})`],
                ] as const
              ).map(([value, label]) => (
                <button
                  key={value}
                  type="button"
                  role="tab"
                  aria-selected={product === value}
                  className={segmentClass(product === value)}
                  onClick={() => {
                    setProduct(value);
                    setVerdict("all");
                    setSettlement("all");
                  }}
                >
                  {label}
                </button>
              ))}
            </div>
            <div
              className="inline-flex flex-wrap gap-0.5 rounded-lg border border-border/60 bg-muted/40 p-1"
              role="tablist"
              aria-label="Outcome"
            >
              {(
                [
                  ["all", `All (${totals.positions ?? positions.length})`],
                  ["watch", `Needs review (${totals.watch ?? 0})`],
                  ["expired", `Expired (${totals.expired ?? 0})`],
                  ["ok", `Received (${totals.ok ?? 0})`],
                  ["potential", `On Potential (${totals.potential ?? 0})`],
                  ["live", `Live (${totals.live ?? 0})`],
                ] as const
              ).map(([value, label]) => (
                <button
                  key={value}
                  type="button"
                  role="tab"
                  aria-selected={verdict === value}
                  className={segmentClass(verdict === value)}
                  onClick={() => setVerdict(value)}
                >
                  {label}
                </button>
              ))}
            </div>
            {!loading && groups.length > 0 ? (
              <div className="inline-flex rounded-lg border border-border/60 bg-muted/40 p-1">
                <button
                  type="button"
                  className={cn(segmentClass(false), "inline-flex items-center gap-1.5")}
                  onClick={toggleExpandCollapseAll}
                  aria-label={allGroupsOpen ? "Collapse all ISINs" : "Expand all ISINs"}
                  title={allGroupsOpen ? "Collapse all" : "Expand all"}
                >
                  {allGroupsOpen ? (
                    <ChevronsDownUp className="size-3.5" />
                  ) : (
                    <ChevronsUpDown className="size-3.5" />
                  )}
                  {allGroupsOpen ? "Collapse" : "Expand"}
                </button>
              </div>
            ) : null}
          </div>
          <div className="flex flex-col gap-1.5">
            <div
              className="inline-flex flex-wrap gap-0.5 rounded-lg border border-border/60 bg-muted/40 p-1"
              role="tablist"
              aria-label="Settlement"
            >
              {(
                [
                  ["all", `All settlements (${totals.settlement_all ?? totals.positions ?? 0})`],
                  ["delivered", `Delivered (${totals.delivered ?? 0})`],
                  ["money_back", `Money Back (${totals.money_back ?? 0})`],
                  ["unsettled", `Unsettled (${totals.unsettled ?? 0})`],
                ] as const
              ).map(([value, label]) => (
                <button
                  key={value}
                  type="button"
                  role="tab"
                  aria-selected={settlement === value}
                  className={segmentClass(settlement === value)}
                  onClick={() => setSettlement(value)}
                >
                  {label}
                </button>
              ))}
            </div>
            {(totals.early_delivery ?? 0) > 0 || (totals.delivery_no_interest ?? 0) > 0 ? (
              <div
                className="inline-flex flex-wrap gap-0.5 rounded-lg border border-border/40 bg-muted/20 p-1"
                role="tablist"
                aria-label="Delivered subsets"
              >
                {(
                  [
                    ["early", `Early delivery (${totals.early_delivery ?? 0})`],
                    [
                      "delivery_no_interest",
                      `Delivered w/o interest (${totals.delivery_no_interest ?? 0})`,
                    ],
                  ] as const
                )
                  .filter(([value]) =>
                    value === "early"
                      ? (totals.early_delivery ?? 0) > 0
                      : (totals.delivery_no_interest ?? 0) > 0,
                  )
                  .map(([value, label]) => (
                    <button
                      key={value}
                      type="button"
                      role="tab"
                      aria-selected={settlement === value}
                      className={segmentClass(settlement === value)}
                      onClick={() => setSettlement(value)}
                    >
                      {label}
                    </button>
                  ))}
              </div>
            ) : null}
          </div>
          <p className="text-[11px] text-muted-foreground">
            Product → Outcome → Settlement. Delivered + Money Back + Unsettled = All. Early / no
            interest are subsets of Delivered.
          </p>
          {error ? <p className="text-destructive text-sm">{error}</p> : null}
        </div>

        <div className="flex w-full min-w-0 flex-wrap items-center justify-end gap-2 sm:ml-auto sm:w-auto">
          <PortfolioIsinCombobox
            options={portfolioIsinOptions}
            value={isin}
            disabled={loading}
            onSelect={applyPortfolioIsin}
            onClear={clearSearch}
          />
          <CustomerFieldsButton onClick={() => setFieldsOpen(true)} disabled={loading} />
          <Button
            type="button"
            size="sm"
            variant="outline"
            onClick={() => void load(product, verdict, settlement, isin)}
            disabled={loading}
            aria-label="Refresh"
          >
            <RefreshCw className={cn("size-3.5", loading && "animate-spin")} />
          </Button>
        </div>
      </div>

      {searchSummary ? (
        <div className="flex flex-wrap items-center gap-x-3 gap-y-1 rounded-lg border border-border/60 bg-muted/20 px-3 py-2 text-sm">
          <span className="font-medium">
            Delivery map for{" "}
            <span className="font-mono tracking-wide">{searchNeedle}</span>
          </span>
          <span className="text-muted-foreground text-xs">
            {searchSummary.holdings} holding{searchSummary.holdings === 1 ? "" : "s"}
            {" · "}
            {searchSummary.structures} product ISIN
            {searchSummary.structures === 1 ? "" : "s"}
            {" · "}
            {searchSummary.clients} client{searchSummary.clients === 1 ? "" : "s"}
            {" · "}
            {searchSummary.deliveredHoldings} delivered
            {searchSummary.deliveredLegs > 0
              ? ` · ${searchSummary.deliveredLegs} matching leg${searchSummary.deliveredLegs === 1 ? "" : "s"}`
              : ""}
            {searchSummary.totalShares > 0
              ? ` · ${formatNum(searchSummary.totalShares, 2)} shares`
              : ""}
          </span>
        </div>
      ) : null}

      {underlyingBreakEven ? (
        <div className="space-y-1.5 rounded-lg border border-border/60 bg-card px-2.5 py-2">
          <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
            <span className="font-medium text-sm">
              Break-even · {underlyingBreakEven.underlyingName}
            </span>
            <span className="font-mono text-muted-foreground text-xs tracking-wide">
              {underlyingBreakEven.underlyingIsin}
            </span>
            <Badge variant="outline" className="h-5 font-normal text-[10px]">
              {underlyingBreakEven.lots.length} delivered lot
              {underlyingBreakEven.lots.length === 1 ? "" : "s"} only
            </Badge>
            {underlyingBreakEven.excludedUndelivered > 0 ? (
              <Badge variant="outline" className="h-5 font-normal text-[10px] text-muted-foreground">
                {underlyingBreakEven.excludedUndelivered} Live / undelivered excluded
              </Badge>
            ) : null}
            <span className="ml-auto text-[11px] text-muted-foreground">
              Structure Notional{" "}
              <span className="font-semibold tabular-nums text-foreground text-sm">
                {formatNum(underlyingBreakEven.structureNotional, 2)}
              </span>
            </span>
          </div>
          <div className="overflow-hidden rounded-md border border-border/60">
            <div className="border-b border-border/50 bg-muted/30 px-2 py-1 text-[11px] font-medium">
              Coupons
            </div>
            <div className="grid lg:grid-cols-2">
              <div className="border-b border-border/50 px-2 py-1.5 lg:border-b-0 lg:border-r">
                <div className="mb-1 flex items-baseline gap-2">
                  <span className="text-[11px] font-medium">Received</span>
                  <span className="text-[10px] text-muted-foreground">
                    Interest / Dividend cash
                  </span>
                </div>
                <div className="flex flex-wrap gap-x-4 gap-y-0.5">
                  <div className="leading-tight">
                    <span className="text-[10px] text-muted-foreground">Coupons </span>
                    <span className="font-semibold tabular-nums text-sm">
                      {formatNum(underlyingBreakEven.couponLedger, 2)}
                    </span>
                  </div>
                  <div className="leading-tight">
                    <span className="text-[10px] text-muted-foreground">Amount </span>
                    <span className="font-semibold tabular-nums text-sm">
                      {formatNum(underlyingBreakEven.amountReceivedLedger, 2)}
                    </span>
                  </div>
                  <div className="leading-tight">
                    <span className="text-[10px] text-muted-foreground">BE </span>
                    <span className="font-semibold tabular-nums text-sm">
                      {underlyingBreakEven.breakEvenLedger !== null
                        ? formatNum(underlyingBreakEven.breakEvenLedger, 4)
                        : "—"}
                    </span>
                  </div>
                </div>
              </div>
              <div className="bg-amber-600/5 px-2 py-1.5">
                <div className="mb-1 flex items-baseline gap-2">
                  <span className="text-[11px] font-medium text-amber-950 dark:text-amber-200">
                    Assumed
                  </span>
                  <span className="text-[10px] text-muted-foreground">
                    BE uses received + assumed ({formatNum(underlyingBreakEven.couponWithPrior, 2)})
                  </span>
                </div>
                <div className="flex flex-wrap gap-x-4 gap-y-0.5">
                  <div className="leading-tight">
                    <span className="text-[10px] text-muted-foreground">Coupons </span>
                    <span className="font-semibold tabular-nums text-sm">
                      {formatNum(underlyingBreakEven.couponPrior, 2)}
                    </span>
                  </div>
                  <div className="leading-tight">
                    <span className="text-[10px] text-muted-foreground">Amount </span>
                    <span className="font-semibold tabular-nums text-sm">
                      {formatNum(underlyingBreakEven.amountReceivedWithPrior, 2)}
                    </span>
                  </div>
                  <div className="leading-tight">
                    <span className="text-[10px] text-muted-foreground">BE </span>
                    <span className="font-semibold tabular-nums text-sm">
                      {underlyingBreakEven.breakEvenWithPrior !== null
                        ? formatNum(underlyingBreakEven.breakEvenWithPrior, 4)
                        : "—"}
                    </span>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div className="flex flex-wrap items-center gap-x-3 gap-y-0.5 text-[11px] text-muted-foreground">
            {underlyingBreakEven.strike !== null ? (
              <span>
                Strike{" "}
                <span className="tabular-nums text-foreground">
                  {formatNum(underlyingBreakEven.strike, 4)}
                </span>
              </span>
            ) : null}
            {underlyingBreakEven.theoreticalQty !== null ? (
              <span>
                Theoretical qty{" "}
                <span className="tabular-nums text-foreground">
                  {formatNum(underlyingBreakEven.theoreticalQty, 4)}
                </span>
              </span>
            ) : null}
            <span>
              Qty delivered{" "}
              <span className="tabular-nums text-foreground">
                {formatNum(underlyingBreakEven.deliveredQty, 2)}
              </span>
            </span>
            {underlyingBreakEven.tentative !== null && underlyingBreakEven.tentative > 0.005 ? (
              <span>
                Tentative{" "}
                <span className="tabular-nums text-foreground">
                  {formatNum(underlyingBreakEven.tentative, 2)}
                </span>
              </span>
            ) : null}
            <span>
              BE = (Σ Notional − Σ Coupon) ÷ Σ Qty
              {underlyingBreakEven.lots.length > 1
                ? ` · ${underlyingBreakEven.lots.length} lots`
                : ""}
            </span>
          </div>

          <div className="grid gap-2 lg:grid-cols-2">
            <div className="overflow-hidden rounded-md border border-emerald-600/20 bg-emerald-600/5">
              <div className="border-b border-emerald-600/15 px-2 py-1 text-[11px] font-medium text-emerald-900 dark:text-emerald-300">
                Included in BE · {underlyingBreakEven.lots.length}
              </div>
              <div className="border-b border-emerald-600/15 bg-emerald-50 text-muted-foreground dark:bg-emerald-950/40">
                <table className="w-full text-[11px]">
                  <colgroup>
                    <col className="w-[42%]" />
                    <col className="w-[16%]" />
                    <col className="w-[14%]" />
                    <col className="w-[14%]" />
                    <col className="w-[14%]" />
                  </colgroup>
                  <thead>
                    <tr>
                      <th rowSpan={2} className="px-1.5 py-0.5 text-left font-medium align-bottom">
                        Structure / Client
                      </th>
                      <th rowSpan={2} className="px-1.5 py-0.5 text-right font-medium align-bottom">
                        Notional
                      </th>
                      <th
                        colSpan={2}
                        className="border-b border-emerald-600/15 px-1.5 py-0.5 text-center font-medium"
                      >
                        Coupons
                      </th>
                      <th rowSpan={2} className="px-1.5 py-0.5 text-right font-medium align-bottom">
                        Qty
                      </th>
                    </tr>
                    <tr>
                      <th className="px-1.5 py-0.5 text-right font-medium">Received</th>
                      <th className="px-1.5 py-0.5 text-right font-medium">Assumed</th>
                    </tr>
                  </thead>
                </table>
              </div>
              <div className="max-h-40 overflow-auto">
                <table className="w-full text-[11px]">
                  <colgroup>
                    <col className="w-[42%]" />
                    <col className="w-[16%]" />
                    <col className="w-[14%]" />
                    <col className="w-[14%]" />
                    <col className="w-[14%]" />
                  </colgroup>
                  <tbody>
                    {underlyingBreakEven.lots.map((lot) => (
                      <tr
                        key={lot.positionKey || `${lot.structureIsin}-${lot.clientLabel}`}
                        className="border-t border-emerald-600/10"
                      >
                        <td className="px-1.5 py-1 align-top">
                          <div className="leading-tight text-foreground">{lot.structureName}</div>
                          <div className="font-mono text-[10px] text-muted-foreground tracking-wide">
                            {lot.structureIsin || "—"}
                            {" · "}
                            {lot.clientLabel}
                            {lot.statusLabel ? ` · ${lot.statusLabel}` : ""}
                          </div>
                        </td>
                        <td className="px-1.5 py-1 text-right tabular-nums align-top">
                          {formatNum(lot.notional, 2)}
                        </td>
                        <td className="px-1.5 py-1 text-right tabular-nums align-top">
                          {formatNum(lot.couponLedger, 2)}
                        </td>
                        <td className="px-1.5 py-1 text-right tabular-nums align-top text-amber-900 dark:text-amber-300">
                          {lot.couponPrior > 0 ? formatNum(lot.couponPrior, 2) : "—"}
                        </td>
                        <td className="px-1.5 py-1 text-right tabular-nums align-top">
                          {formatNum(lot.deliveredQty, 2)}
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </div>

            <div className="overflow-hidden rounded-md border border-border/60 bg-muted/20">
              <div className="border-b border-border/50 px-2 py-1 text-[11px] font-medium text-muted-foreground">
                Excluded from BE · {underlyingBreakEven.excluded.length}
              </div>
              {underlyingBreakEven.excluded.length === 0 ? (
                <p className="px-2 py-2 text-[11px] text-muted-foreground">
                  No Live / undelivered holdings for this underlying.
                </p>
              ) : (
                <>
                  <div className="border-b border-border/50 bg-muted text-muted-foreground">
                    <table className="w-full text-[11px]">
                      <colgroup>
                        <col className="w-[58%]" />
                        <col className="w-[42%]" />
                      </colgroup>
                      <thead>
                        <tr>
                          <th className="px-1.5 py-0.5 text-left font-medium">Structure / Client</th>
                          <th className="px-1.5 py-0.5 text-left font-medium">Why excluded</th>
                        </tr>
                      </thead>
                    </table>
                  </div>
                  <div className="max-h-40 overflow-auto">
                    <table className="w-full text-[11px]">
                      <colgroup>
                        <col className="w-[58%]" />
                        <col className="w-[42%]" />
                      </colgroup>
                      <tbody>
                        {underlyingBreakEven.excluded.map((row) => (
                          <tr
                            key={row.positionKey || `${row.structureIsin}-${row.clientLabel}`}
                            className="border-t border-border/40"
                          >
                            <td className="px-1.5 py-1 align-top">
                              <div className="leading-tight text-foreground">{row.structureName}</div>
                              <div className="text-[10px] text-muted-foreground">
                                <span className="font-mono tracking-wide">
                                  {row.structureIsin || "—"}
                                </span>
                                {" · "}
                                {row.clientLabel}
                                {row.statusLabel ? ` · ${row.statusLabel}` : ""}
                              </div>
                            </td>
                            <td className="px-1.5 py-1 align-top text-muted-foreground">
                              {row.reason}
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                </>
              )}
            </div>
          </div>
        </div>
      ) : null}

      <p className="text-muted-foreground text-xs">
        Structure: Live = interest only (pre-FVD) · On Potential = awaiting FVD · Expired = past
        FVD — Deliver if tagged, else Money Back · Needs review = delivery/early without interest ·
        Received = Accu/Option settled income
      </p>

      {loading ? (
        <DeliveredHoldingsHistorySkeleton />
      ) : groups.length === 0 && !error ? (
        <p className="py-10 text-center text-muted-foreground text-sm">
          {searchNeedle
            ? `No holdings delivered or booked for ${searchNeedle} in the current Portfolio Scope.`
            : "No holdings match this filter."}
        </p>
      ) : (
        <div className="space-y-2">
          {groups.map((group) => {
            const open = openKeys.has(group.key);
            const hasName = Boolean(group.name);
            const title = group.name || group.isin;

            return (
              <div
                key={group.key}
                className="overflow-hidden rounded-lg border border-border/60 bg-card"
              >
                <button
                  type="button"
                  className={cn(
                    "flex w-full flex-wrap items-center gap-2 px-3 py-2.5 text-left transition-colors hover:bg-muted/40",
                    open && "bg-muted/30",
                  )}
                  onClick={() => toggleGroup(group.key)}
                >
                  <ChevronRight
                    className={cn(
                      "size-4 shrink-0 text-muted-foreground transition-transform",
                      open && "rotate-90",
                    )}
                  />
                  <div className="min-w-0 flex-1">
                    <div className="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1">
                      <span className="font-medium text-sm leading-snug">{title}</span>
                      {hasName && group.isin !== "—" ? (
                        <span className="rounded bg-muted px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground">
                          {group.isin}
                        </span>
                      ) : null}
                    </div>
                    <div className="mt-1.5 flex flex-wrap items-center gap-1.5">
                      {group.products.map((productLabel) => (
                        <Badge
                          key={productLabel}
                          variant="secondary"
                          className={cn(
                            "border-transparent font-medium text-[10px]",
                            productClass(productLabel),
                          )}
                        >
                          {productLabel}
                        </Badge>
                      ))}
                      <Badge variant="outline" className="font-normal tabular-nums text-[10px]">
                        {group.positions.length} holding
                        {group.positions.length === 1 ? "" : "s"}
                        {group.clientCount > 0
                          ? ` · ${group.clientCount} client${group.clientCount === 1 ? "" : "s"}`
                          : ""}
                      </Badge>
                      {group.watchCount > 0 ? (
                        <Badge
                          variant="secondary"
                          className={cn("font-medium text-[10px]", verdictClass("watch"))}
                        >
                          {group.watchCount} {verdictGroupLabel("watch")}
                        </Badge>
                      ) : null}
                      {group.expiredCount > 0 ? (
                        <Badge
                          variant="secondary"
                          className={cn("font-medium text-[10px]", verdictClass("expired"))}
                        >
                          {group.expiredCount} {verdictGroupLabel("expired")}
                        </Badge>
                      ) : null}
                      {group.okCount > 0 ? (
                        <Badge
                          variant="secondary"
                          className={cn("font-medium text-[10px]", verdictClass("ok"))}
                        >
                          {group.okCount} {verdictGroupLabel("ok")}
                        </Badge>
                      ) : null}
                      {group.potentialCount > 0 ? (
                        <Badge
                          variant="secondary"
                          className={cn("font-medium text-[10px]", verdictClass("potential"))}
                        >
                          {group.potentialCount} {verdictGroupLabel("potential")}
                        </Badge>
                      ) : null}
                      {group.liveCount > 0 ? (
                        <Badge
                          variant="secondary"
                          className={cn("font-medium text-[10px]", verdictClass("live"))}
                        >
                          {group.liveCount} {verdictGroupLabel("live")}
                        </Badge>
                      ) : null}
                    </div>
                    <div className="mt-1 flex flex-wrap gap-x-3 gap-y-0.5 text-[11px] text-muted-foreground">
                      <span>
                        Delivery{" "}
                        <span className="font-medium tabular-nums text-foreground">
                          {group.deliveryCount}/{group.positions.length}
                        </span>
                      </span>
                      <span>
                        Early{" "}
                        <span className="font-medium tabular-nums text-foreground">
                          {group.earlyCount}
                        </span>
                      </span>
                      <span>
                        Interest{" "}
                        <span className="font-medium tabular-nums text-foreground">
                          {group.interestCount}
                        </span>
                      </span>
                      {group.totalShares > 0 ? (
                        <span>
                          Shares{" "}
                          <span className="font-medium tabular-nums text-foreground">
                            {formatNum(group.totalShares, 2)}
                          </span>
                        </span>
                      ) : null}
                      {group.totalInterest > 0 ? (
                        <span>
                          Int.{" "}
                          <span className="font-medium tabular-nums text-foreground">
                            {formatNum(group.totalInterest, 2)}
                          </span>
                        </span>
                      ) : null}
                    </div>
                  </div>
                </button>

                {open ? (
                  <div className="border-t border-border/60">
                    <div className="overflow-x-auto">
                      <Table className="w-full min-w-[1100px]">
                        <TableHeader>
                          <TableRow className="bg-muted/20 hover:bg-muted/20">
                            <TableHead className="h-8 w-8 px-2 align-middle" />
                            {visibleColumns.map((column) => (
                              <TableHead
                                key={column.key}
                                className={cn(
                                  "h-8 px-3 align-middle text-[11px] font-medium",
                                  column.headClassName,
                                )}
                              >
                                {column.label}
                              </TableHead>
                            ))}
                          </TableRow>
                        </TableHeader>
                        <TableBody>
                          {group.positions.map((pos, rowIndex) => {
                            const rowOpen = expandedRow === pos.position_key;
                            const childEvents = eventsByPosition.get(pos.position_key) ?? [];

                            return (
                              <React.Fragment key={pos.position_key}>
                                <TableRow
                                  className={cn(
                                    "cursor-pointer",
                                    rowIndex % 2 === 0 ? "bg-muted/5" : undefined,
                                    rowOpen && "bg-muted/40",
                                  )}
                                  onClick={() =>
                                    setExpandedRow(rowOpen ? null : pos.position_key)
                                  }
                                >
                                  <TableCell className="w-8 px-2 py-2 align-top">
                                    <ChevronRight
                                      className={cn(
                                        "mt-0.5 size-4 text-muted-foreground transition-transform",
                                        rowOpen && "rotate-90",
                                      )}
                                    />
                                  </TableCell>
                                  {visibleColumns.map((column) => {
                                    const title =
                                      column.key === "interest"
                                        ? interestCouponTooltip(pos)
                                        : column.key === "note"
                                          ? pos.verdict_note || pos.potential_reason
                                          : column.key === "client"
                                            ? String(
                                                pos.client_label || pos.user_label || "",
                                              ).trim() || undefined
                                            : column.key === "rm"
                                              ? pos.rm_label
                                              : undefined;
                                    return (
                                      <TableCell
                                        key={column.key}
                                        className={cn(
                                          "px-3 py-2 align-top text-xs leading-snug",
                                          column.key === "note" && "truncate",
                                          column.key === "rm" && "truncate",
                                          column.key === "uid" && "truncate",
                                          column.cellClassName,
                                        )}
                                        title={title}
                                      >
                                        {renderDeliveredHoldingsCell(
                                          column,
                                          pos,
                                          searchNeedle,
                                        )}
                                      </TableCell>
                                    );
                                  })}
                                </TableRow>
                                {rowOpen ? (
                                  <TableRow className="border-t bg-muted/30 hover:bg-muted/30">
                                    <TableCell
                                      colSpan={visibleColumns.length + 1}
                                      className="p-0"
                                    >
                                      <EventEvidence events={childEvents} position={pos} />
                                    </TableCell>
                                  </TableRow>
                                ) : null}
                              </React.Fragment>
                            );
                          })}
                        </TableBody>
                      </Table>
                    </div>
                  </div>
                ) : null}
              </div>
            );
          })}
        </div>
      )}

      <CustomerFieldsPanel
        open={fieldsOpen}
        onOpenChange={setFieldsOpen}
        catalog={DELIVERED_HOLDINGS_COLUMNS}
        visibility={columnVisibility as Record<string, boolean>}
        order={columnOrder}
        lockedKeys={DELIVERED_HOLDINGS_LOCKED_KEYS}
        title="Fields"
        description="Choose which columns to show and drag to reorder. Client, Structure / Underlyings, and Interest stay visible."
        onToggle={setColumnVisible}
        onReorder={reorderShown}
        onHideAll={hideAll}
      />
    </div>
  );
}
