"use client";

import * as React from "react";
import { resolveCustomerTenant } from "@/app/customer/_lib/resolve-customer-tenant";
import { useParams, usePathname, useSearchParams } from "next/navigation";
import {
  addDays,
  addMonths,
  endOfMonth,
  format,
  isToday,
  parseISO,
  startOfMonth,
  subDays,
  subMonths,
} from "date-fns";
import {
  ChevronLeft,
  ChevronRight,
} from "lucide-react";

import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { cn } from "@/lib/utils";

import { ReportLoadingPanel } from "@/app/customer/[tenant]/reports/_shared/components/report-loading-panel";
import type { ImpersonationScopeChangedDetail } from "@/app/customer/_lib/admin/impersonation-scope";
import { usePortfolioScopePageReset } from "@/app/customer/_lib/admin/use-portfolio-scope-page-reset";
import {
  CustomerFieldsPanel,
} from "@/app/customer/_components/customer-fields-panel";
import type { CustomerColumnPrefs } from "@/app/customer/_lib/customer-grid-columns";
import { useCustomerTableColumnPrefs } from "@/app/customer/_lib/use-customer-table-column-prefs";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { isStructureReportAsset } from "../../_lib/cashflow-asset-class";
import { saveCashflowColumnPrefsClient } from "../../_lib/cashflow-api";
import {
  buildCashflowPageSearchParams,
  mergeCashflowFiltersFromBootstrap,
  parseCashflowUrlBootstrap,
} from "../../_lib/parse-cashflow-url-bootstrap";
import { useCashflowCalendar } from "../../_lib/use-cashflow-calendar";
import { CashflowDaySheet } from "./cashflow-day-sheet";
import { CashflowEventChip } from "./cashflow-event-chip";
import {
  CASHFLOW_CHIP_FIELD_GROUPS,
  CASHFLOW_CHIP_FIELDS_CATALOG,
  CASHFLOW_DETAIL_FIELDS_CATALOG,
  CASHFLOW_LOCKED_KEYS,
  isCashflowFieldVisible,
} from "./cashflow-fields-catalog";
import { CashflowLegendPopover } from "./cashflow-legend-popover";
import { CashflowReportHeader } from "./cashflow-report-header";
import { CashflowStructureStatusIcon } from "./cashflow-structure-status-icon";
import {
  type CashflowBankOption,
  type CashflowFilters,
  type CashflowViewMode,
  buildDefaultCashflowFilters,
  cashflowServerFilterIds,
} from "./schema";
import {
  WEEKDAY_LABELS,
  dateKey,
  filterCashflowEvents,
  getCalendarDays,
  getWeekDays,
  groupEventsByDate,
  isCurrentMonth,
  isNegativeAmount,
} from "./utils";
import { useChanged } from "@/hooks/use-changed";

const MAX_VISIBLE_EVENTS = 3;

export function CashflowView() {
  const params = useParams<{ tenant?: string }>();
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const urlBootstrap = React.useMemo(
    () => parseCashflowUrlBootstrap(searchParams),
    [searchParams],
  );
  const tenant = typeof params?.tenant === "string" && params.tenant.trim() ? params.tenant.trim() : resolveCustomerTenant();

  const suppressUrlSyncRef = React.useRef(false);
  const [anchor, setAnchor] = React.useState(() => urlBootstrap.anchor);
  const [view, setView] = React.useState<CashflowViewMode>(() => urlBootstrap.view);
  const [filters, setFilters] = React.useState<CashflowFilters>(() => ({
    ...buildDefaultCashflowFilters({ bankIds: [], assetClasses: [] }),
    search: urlBootstrap.filters.search,
    eventTypes: urlBootstrap.filters.eventTypes,
    structureStatusIds: urlBootstrap.filters.structureStatusIds,
    bankIds: urlBootstrap.filters.bankIds,
    assetClasses: urlBootstrap.filters.assetClasses,
  }));
  const [selectedDate, setSelectedDate] = React.useState<string | null>(null);
  const [sheetOpen, setSheetOpen] = React.useState(false);
  const [refreshKey, setRefreshKey] = React.useState(0);
  const [fieldsOpen, setFieldsOpen] = React.useState(false);
  const [fieldsTab, setFieldsTab] = React.useState<"chips" | "details">("chips");
  const filtersSyncedRef = React.useRef(false);

  // Keep full picker catalogs across filtered refetches (Yii always returns them, but
  // preserve the widest list if a response omits options while filters are active).
  const [bankOptions, setBankOptions] = React.useState<CashflowBankOption[]>([]);
  const [assetClassOptions, setAssetClassOptions] = React.useState<Record<string, string>>({});

  // Refetch whenever the visible period changes (month/week/day), including year boundaries.
  const { dateFrom, dateTo } = React.useMemo(() => {
    if (view === "week") {
      const days = getWeekDays(anchor);
      return { dateFrom: dateKey(days[0]), dateTo: dateKey(days[6]) };
    }
    if (view === "day") {
      const key = dateKey(anchor);
      return { dateFrom: key, dateTo: key };
    }
    // Month + list: the displayed calendar month (handles Dec↔Jan year changes).
    return {
      dateFrom: format(startOfMonth(anchor), "yyyy-MM-dd"),
      dateTo: format(endOfMonth(anchor), "yyyy-MM-dd"),
    };
  }, [view, anchor]);

  const bankOptionIds = React.useMemo(() => bankOptions.map((bank) => bank.id), [bankOptions]);
  const assetClassCodes = React.useMemo(() => Object.keys(assetClassOptions), [assetClassOptions]);

  const queryBankIds = cashflowServerFilterIds(filters.bankIds, bankOptionIds);
  const queryAssetClasses = cashflowServerFilterIds(filters.assetClasses, assetClassCodes);

  const { data, isLoading, errorMessage, columnPrefs } = useCashflowCalendar(tenant, {
    dateFrom,
    dateTo,
    bankIds: queryBankIds,
    assetClasses: queryAssetClasses,
    eventTypes: filters.eventTypes,
    structureStatusIds: filters.structureStatusIds,
    refreshKey,
  });

  const chipPrefsRef = React.useRef<CustomerColumnPrefs>({ visibility: {}, order: [] });
  const detailPrefsRef = React.useRef<CustomerColumnPrefs>({ visibility: {}, order: [] });

  const saveChipPrefs = React.useCallback(async (prefs: CustomerColumnPrefs) => {
    await saveCashflowColumnPrefsClient({
      visibility: prefs.visibility,
      order: prefs.order,
      totalsVisibility: detailPrefsRef.current.visibility,
      totalsOrder: detailPrefsRef.current.order,
    });
  }, []);

  const {
    columnVisibility: chipVisibilityState,
    columnOrder: chipOrder,
    hideAll: hideAllChipFields,
    setColumnVisible: setChipFieldVisible,
    reorderShown: reorderChipFields,
  } = useCustomerTableColumnPrefs({
    catalog: CASHFLOW_CHIP_FIELDS_CATALOG,
    initialPrefs: columnPrefs,
    lockedKeys: [...CASHFLOW_LOCKED_KEYS],
    savePrefs: saveChipPrefs,
  });

  const detailInitialPrefs = React.useMemo<CustomerColumnPrefs | null>(
    () =>
      columnPrefs
        ? {
            visibility: columnPrefs.totalsVisibility ?? {},
            order: columnPrefs.totalsOrder ?? [],
          }
        : null,
    [columnPrefs],
  );

  const saveDetailPrefs = React.useCallback(async (prefs: CustomerColumnPrefs) => {
    await saveCashflowColumnPrefsClient({
      visibility: chipPrefsRef.current.visibility,
      order: chipPrefsRef.current.order,
      totalsVisibility: prefs.visibility,
      totalsOrder: prefs.order,
    });
  }, []);

  const {
    columnVisibility: detailVisibilityState,
    columnOrder: detailOrder,
    hideAll: hideAllDetailFields,
    setColumnVisible: setDetailFieldVisible,
    reorderShown: reorderDetailFields,
  } = useCustomerTableColumnPrefs({
    catalog: CASHFLOW_DETAIL_FIELDS_CATALOG,
    initialPrefs: detailInitialPrefs,
    lockedKeys: [...CASHFLOW_LOCKED_KEYS],
    savePrefs: saveDetailPrefs,
  });

  const chipVisibility = chipVisibilityState as Record<string, boolean>;
  const detailVisibility = detailVisibilityState as Record<string, boolean>;

  React.useEffect(() => {
    chipPrefsRef.current = { visibility: chipVisibility, order: chipOrder };
  }, [chipVisibility, chipOrder]);

  React.useEffect(() => {
    detailPrefsRef.current = { visibility: detailVisibility, order: detailOrder };
  }, [detailVisibility, detailOrder]);

  const showField = React.useCallback(
    (key: string) => isCashflowFieldVisible(chipVisibility, key),
    [chipVisibility],
  );

  // Merge newly arrived catalogs; retain what we already have during refetch.
  if (useChanged(data) && data) {
    if (data.banks.length > 0) {
      setBankOptions((prev) => {
        const byId = new Map(prev.map((bank) => [bank.id, bank]));
        for (const bank of data.banks) byId.set(bank.id, bank);
        return [...byId.values()];
      });
    }
    if (Object.keys(data.assetClass).length > 0) {
      setAssetClassOptions((prev) => ({ ...prev, ...data.assetClass }));
    }
  }

  // Once picker catalogs are available, default every bank + asset class to selected.
  React.useEffect(() => {
    if (filtersSyncedRef.current) return;
    if (bankOptionIds.length === 0 || assetClassCodes.length === 0) return;
    filtersSyncedRef.current = true;

    const hasUrlPickerFilters =
      urlBootstrap.filters.bankIds.length > 0 || urlBootstrap.filters.assetClasses.length > 0;

    if (hasUrlPickerFilters) {
      setFilters(
        mergeCashflowFiltersFromBootstrap(urlBootstrap, {
          bankIds: bankOptionIds,
          assetClasses: assetClassCodes,
        }),
      );
      return;
    }

    setFilters((prev) => ({
      ...buildDefaultCashflowFilters({
        bankIds: bankOptionIds,
        assetClasses: assetClassCodes,
        search: prev.search,
        structureStatusIds: prev.structureStatusIds,
      }),
      eventTypes: prev.eventTypes,
    }));
  }, [bankOptionIds, assetClassCodes, urlBootstrap]);

  // Keep the browser URL in sync so filters are shareable and survive refresh.
  React.useEffect(() => {
    if (suppressUrlSyncRef.current) return;

    const params = buildCashflowPageSearchParams({
      view,
      anchor,
      filters,
      bankOptionIds,
      assetClassCodes,
    });
    const qs = params.toString();
    const nextUrl = qs ? `${pathname}?${qs}` : pathname;
    const currentUrl = `${window.location.pathname}${window.location.search}`;
    if (nextUrl !== currentUrl) {
      window.history.replaceState(window.history.state, "", nextUrl);
    }
  }, [view, anchor, filters, bankOptionIds, assetClassCodes, pathname]);

  // Portfolio Scope Apply / banner Clear: drop bank/search restrictions so the
  // calendar reloads scoped clients without stale filters wiping the month.
  usePortfolioScopePageReset(
    React.useCallback((_detail: ImpersonationScopeChangedDetail) => {
      suppressUrlSyncRef.current = true;
      filtersSyncedRef.current = false;
      setBankOptions([]);
      setAssetClassOptions({});
      setFilters(buildDefaultCashflowFilters({ bankIds: [], assetClasses: [] }));
      setSelectedDate(null);
      setSheetOpen(false);
      setRefreshKey((value) => value + 1);
      window.history.replaceState(window.history.state, "", pathname);
      window.setTimeout(() => {
        suppressUrlSyncRef.current = false;
      }, 0);
    }, [pathname]),
  );

  // Portfolio Scope Apply/Clear: drop bank/search restrictions so the calendar
  // reloads scoped clients without stale ids filters wiping the month.
  usePortfolioScopePageReset(
    React.useCallback((_detail: ImpersonationScopeChangedDetail) => {
      filtersSyncedRef.current = false;
      setBankOptions([]);
      setAssetClassOptions({});
      setFilters(buildDefaultCashflowFilters({ bankIds: [], assetClasses: [] }));
      setSelectedDate(null);
      setSheetOpen(false);
      setRefreshKey((value) => value + 1);
    }, []),
  );

  // Banner Clear / Apply with empty selection still need a data refresh even when
  // clearPageSearchParams is false — handled by the calendar list hook.
  // Apply / banner Clear always send clearPageSearchParams: true.

  const filteredEvents = React.useMemo(
    () => filterCashflowEvents(data?.events ?? [], filters),
    [data, filters],
  );
  const eventsByDate = React.useMemo(() => groupEventsByDate(filteredEvents), [filteredEvents]);

  const monthDays = React.useMemo(() => getCalendarDays(anchor), [anchor]);
  const weekDays = React.useMemo(() => getWeekDays(anchor), [anchor]);

  const selectedDayEvents = selectedDate ? (eventsByDate.get(selectedDate) ?? []) : [];
  const resetFilters = React.useCallback(() => {
    setFilters(
      buildDefaultCashflowFilters({
        bankIds: bankOptionIds,
        assetClasses: assetClassCodes,
      }),
    );
  }, [bankOptionIds, assetClassCodes]);

  const legend = React.useMemo(() => {
    const map = new Map<string, { label: string; color: string; count: number }>();
    for (const event of filteredEvents) {
      const key = event.assetClassCode || event.assetClassLabel || "other";
      const existing = map.get(key);
      if (existing) {
        existing.count += 1;
      } else {
        map.set(key, { label: event.assetClassLabel || "Other", color: event.color, count: 1 });
      }
    }
    return [...map.values()].sort((a, b) => b.count - a.count);
  }, [filteredEvents]);

  const openDay = (date: string) => {
    setSelectedDate(date);
    setSheetOpen(true);
  };

  const goToday = () => setAnchor(new Date());

  const navigatePrev = () => {
    setAnchor((d) => {
      if (view === "month" || view === "list") return subMonths(d, 1);
      if (view === "week") return subDays(d, 7);
      return subDays(d, 1);
    });
  };

  const navigateNext = () => {
    setAnchor((d) => {
      if (view === "month" || view === "list") return addMonths(d, 1);
      if (view === "week") return addDays(d, 7);
      return addDays(d, 1);
    });
  };

  const headerTitle =
    view === "month"
      ? format(anchor, "MMMM yyyy")
      : view === "week"
        ? `Week of ${format(getWeekDays(anchor)[0], "d MMM yyyy")}`
        : view === "day"
          ? format(anchor, "EEEE, d MMMM yyyy")
          : `${format(anchor, "MMMM yyyy")} — agenda`;

  const listEvents = React.useMemo(() => {
    const monthStart = format(anchor, "yyyy-MM");
    return filteredEvents.filter((e) => e.date.startsWith(monthStart)).sort((a, b) => a.start.localeCompare(b.start));
  }, [filteredEvents, anchor]);

  return (
    <div className="flex h-full min-h-0 min-w-0 flex-1 flex-col gap-3 overflow-hidden">
      <div className="flex shrink-0 flex-col gap-3">
        <CashflowReportHeader
          filteredEventCount={filteredEvents.length}
          totalsByAssetClass={data?.totalsByAssetClass ?? []}
          isLoading={isLoading}
          errorMessage={errorMessage}
          filters={filters}
          onFiltersChange={setFilters}
          bankOptions={bankOptions}
          assetClassOptions={assetClassOptions}
          bankOptionIds={bankOptionIds}
          assetClassCodes={assetClassCodes}
          onResetFilters={resetFilters}
          onOpenFields={() => setFieldsOpen(true)}
          onRefresh={() => setRefreshKey((k) => k + 1)}
          view={view}
          onViewChange={setView}
          headerTitle={headerTitle}
          onNavigatePrev={navigatePrev}
          onNavigateNext={navigateNext}
          onGoToday={goToday}
          navActions={<CashflowLegendPopover legend={legend} />}
        />
      </div>

      <ReportLoadingPanel
        loading={isLoading}
        label="Loading cashflow…"
        minHeightClassName="min-h-0"
        className={cn(
          "flex min-h-0 flex-1 flex-col overflow-hidden",
          isLoading && "pointer-events-none",
        )}
      >
      {view === "month" ? (
        <Card className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden border-border/80 py-0 shadow-sm">
          <CardContent className="flex min-h-0 flex-1 flex-col overflow-hidden p-0">
            {/*
              Gap-grid borders: parent bg + gap-px = uniform 1px lines (no stacked cell borders).
              Outer border on this wrapper restores top/side edges. Scroll stays on body/events only.
            */}
            <div className="flex min-h-0 flex-1 flex-col overflow-hidden border border-border/60">
              <div className="scrollbar-slim grid shrink-0 grid-cols-7 gap-px overflow-y-scroll border-b border-border/60 bg-border/60 [scrollbar-gutter:stable]">
                {WEEKDAY_LABELS.map((label) => (
                  <div
                    key={label}
                    className="box-border bg-muted/40 px-2 py-2.5 text-center font-semibold text-[11px] text-muted-foreground uppercase tracking-wide"
                  >
                    {label}
                  </div>
                ))}
              </div>
              <div className="scrollbar-slim min-h-0 flex-1 overflow-y-auto overscroll-contain [scrollbar-gutter:stable]">
                <div className="grid grid-cols-7 gap-px bg-border/60">
                  {monthDays.map((day) => {
                    const key = dateKey(day);
                    const dayEvents = eventsByDate.get(key) ?? [];
                    const inMonth = isCurrentMonth(day, anchor);
                    const today = isToday(day);
                    const visible = dayEvents.slice(0, MAX_VISIBLE_EVENTS);
                    const overflow = dayEvents.length - visible.length;

                    return (
                      <div
                        key={key}
                        className={cn(
                          // Opaque cell bg covers the gap color → reveals exact 1px grid lines.
                          "group/cell box-border flex min-h-[148px] flex-col border-0 bg-card p-1.5 transition-colors",
                          !inMonth && "bg-muted",
                          today && "bg-sky-50 ring-1 ring-inset ring-sky-500/25 dark:bg-sky-950/40",
                          dayEvents.length > 0 && "hover:bg-muted/80",
                        )}
                      >
                        <div className="mb-1.5 flex shrink-0 items-center justify-between gap-1">
                          <button
                            type="button"
                            onClick={() => openDay(key)}
                            className={cn(
                              "flex size-7 items-center justify-center rounded-full text-sm tabular-nums transition-colors",
                              today && "bg-sky-600 font-semibold text-white",
                              !today && inMonth && "font-medium text-foreground/90 hover:bg-muted",
                              !inMonth && "text-muted-foreground/45",
                            )}
                          >
                            {format(day, "d")}
                          </button>
                          {dayEvents.length > 0 ? (
                            <span className="rounded-full bg-muted/80 px-1.5 py-0.5 font-medium text-[9px] text-muted-foreground tabular-nums opacity-0 transition-opacity group-hover/cell:opacity-100">
                              {dayEvents.length}
                            </span>
                          ) : null}
                        </div>
                        <div className="scrollbar-slim flex min-h-0 flex-1 flex-col gap-1 overflow-y-auto bg-clip-padding pr-0.5">
                          {visible.map((event) => (
                            <CashflowEventChip
                              key={event.id}
                              event={event}
                              compact
                              onClick={() => openDay(key)}
                              chipVisibility={chipVisibility}
                              detailVisibility={detailVisibility}
                              detailOrder={detailOrder}
                            />
                          ))}
                          {overflow > 0 ? (
                            <button
                              type="button"
                              onClick={() => openDay(key)}
                              className="rounded-lg border border-border/70 bg-card px-2 py-1 text-center font-medium text-[10px] text-foreground/70 shadow-sm transition-colors hover:border-border hover:bg-muted hover:text-foreground"
                            >
                              +{overflow} more
                            </button>
                          ) : null}
                        </div>
                      </div>
                    );
                  })}
                </div>
              </div>
            </div>
          </CardContent>
        </Card>
      ) : null}

      {view === "week" ? (
        <div className="grid min-h-0 min-w-0 flex-1 grid-cols-7 gap-px overflow-hidden rounded-xl border border-border/60 bg-border/60">
          {weekDays.map((day) => {
            const key = dateKey(day);
            const dayEvents = eventsByDate.get(key) ?? [];
            const today = isToday(day);
            return (
              <div
                key={key}
                className={cn(
                  "flex h-full min-h-0 min-w-0 flex-col border-0 bg-card",
                  today && "bg-sky-50 ring-1 ring-inset ring-sky-500/25 dark:bg-sky-950/40",
                )}
              >
                <div className={cn("shrink-0 border-b border-border/50 px-3 py-3 text-center", today ? "bg-sky-500/10" : "bg-muted/40")}>
                  <p className="font-medium text-muted-foreground text-[11px] uppercase tracking-wide">
                    {format(day, "EEE")}
                  </p>
                  <button
                    type="button"
                    onClick={() => openDay(key)}
                    className={cn(
                      "mt-1 inline-flex size-9 items-center justify-center rounded-full font-semibold text-lg tabular-nums transition-colors",
                      today ? "bg-sky-600 text-white" : "hover:bg-muted",
                    )}
                  >
                    {format(day, "d")}
                  </button>
                  <p className="mt-1 text-muted-foreground text-[10px] tabular-nums">
                    {dayEvents.length} event{dayEvents.length === 1 ? "" : "s"}
                  </p>
                </div>
                <div className="scrollbar-slim min-h-0 flex-1 space-y-1.5 overflow-y-auto bg-clip-padding p-2 pr-1.5">
                  {dayEvents.length === 0 ? (
                    <p className="py-8 text-center text-muted-foreground text-xs">No events</p>
                  ) : (
                    dayEvents.map((event) => (
                      <CashflowEventChip
                        key={event.id}
                        event={event}
                        onClick={() => openDay(key)}
                        chipVisibility={chipVisibility}
                        detailVisibility={detailVisibility}
                        detailOrder={detailOrder}
                      />
                    ))
                  )}
                </div>
              </div>
            );
          })}
        </div>
      ) : null}

      {view === "day" ? (
        <div className="box-border flex min-h-0 w-full flex-1 flex-col overflow-hidden rounded-xl border border-border/60 bg-card">
          <div className="flex shrink-0 items-center justify-between gap-3 border-b border-border/60 bg-muted/40 px-4 py-3">
            <div>
              <p className="font-semibold text-lg tracking-tight">{format(anchor, "EEEE, d MMMM yyyy")}</p>
              <p className="text-muted-foreground text-sm tabular-nums">
                {(eventsByDate.get(dateKey(anchor)) ?? []).length} events
              </p>
            </div>
            <div className="inline-flex gap-0.5 rounded-lg border border-border/60 bg-background p-1">
              <Button variant="ghost" size="icon" className="size-8" onClick={() => setAnchor((d) => addDays(d, -1))}>
                <ChevronLeft className="size-4" />
              </Button>
              <Button variant="ghost" size="icon" className="size-8" onClick={() => setAnchor((d) => addDays(d, 1))}>
                <ChevronRight className="size-4" />
              </Button>
            </div>
          </div>
          <div className="scrollbar-slim min-h-0 flex-1 overflow-y-auto overscroll-contain bg-clip-padding p-4">
            <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
              {(eventsByDate.get(dateKey(anchor)) ?? []).length === 0 ? (
                <p className="col-span-full rounded-xl border border-dashed border-border/60 py-16 text-center text-muted-foreground text-sm">
                  No events on this day.
                </p>
              ) : (
                (eventsByDate.get(dateKey(anchor)) ?? []).map((event) => (
                  <CashflowEventChip
                    key={event.id}
                    event={event}
                    onClick={() => openDay(dateKey(anchor))}
                    className="rounded-lg border-border/60 shadow-sm hover:translate-y-0"
                    chipVisibility={chipVisibility}
                    detailVisibility={detailVisibility}
                    detailOrder={detailOrder}
                  />
                ))
              )}
            </div>
          </div>
        </div>
      ) : null}

      {view === "list" ? (
        <div className="box-border flex min-h-0 w-full flex-1 flex-col overflow-hidden rounded-xl border border-border/60 bg-card">
          <div className="scrollbar-slim min-h-0 flex-1 overflow-y-auto overscroll-contain bg-clip-padding">
            {listEvents.length === 0 ? (
              <p className="py-16 text-center text-muted-foreground text-sm">No events in this period.</p>
            ) : (
              listEvents.map((event, index) => {
                const negative = isNegativeAmount(event.amount);
                const isLast = index === listEvents.length - 1;
                return (
                  <button
                    key={event.id}
                    type="button"
                    onClick={() => openDay(event.date)}
                    className={cn(
                      "group box-border flex w-full flex-col gap-2 bg-card bg-clip-padding px-4 py-3.5 text-left transition-colors hover:bg-muted/40 sm:flex-row sm:items-center sm:justify-between",
                      !isLast && "border-b border-border/60",
                    )}
                  >
                    <div className="flex min-w-0 items-start gap-3">
                      {showField("date") ? (
                        <div className="flex w-16 shrink-0 flex-col items-center rounded-xl border border-border/60 bg-muted/40 px-2 py-2">
                          <p className="font-semibold text-sm tabular-nums leading-none">{format(parseISO(event.date), "dd")}</p>
                          <p className="mt-1 text-[10px] text-muted-foreground uppercase tracking-wide">
                            {format(parseISO(event.date), "MMM")}
                          </p>
                        </div>
                      ) : null}
                      <div className="min-w-0 pt-0.5">
                        <div className="flex flex-wrap items-center gap-2">
                          {isStructureReportAsset(event.assetClassCode) && showField("structureStatus") ? (
                            <CashflowStructureStatusIcon
                              earlyRedemption={event.earlyRedemption}
                              delivery={event.delivery}
                              size="md"
                            />
                          ) : null}
                          {showField("type") ? (
                            <span
                              className="inline-flex items-center rounded-full px-2 py-0.5 font-semibold text-[10px] uppercase tracking-[0.1em]"
                              style={{
                                backgroundColor: `${event.color}22`,
                                color: event.textColor,
                              }}
                            >
                              {event.shortLabel}
                            </span>
                          ) : null}
                          {showField("isin") && event.isin ? (
                            <span className="font-mono text-[11px] text-muted-foreground">{event.isin}</span>
                          ) : null}
                          {showField("user") && (event.userLabel || event.uidTitle) ? (
                            <span className="text-[11px] text-muted-foreground">
                              {event.userLabel || event.uidTitle}
                            </span>
                          ) : null}
                          {showField("refId") && event.heading ? (
                            <span className="text-[11px] text-muted-foreground">{event.heading}</span>
                          ) : null}
                        </div>
                        {showField("name") ? (
                          <p className="mt-1.5 truncate text-sm text-foreground/85">{event.name || event.title}</p>
                        ) : null}
                        {(showField("underlyingName") ||
                          showField("underlyingIsin") ||
                          showField("underlyingCurrency")) &&
                        event.underlyings &&
                        event.underlyings.length > 0 ? (
                          <div className="mt-1.5 space-y-1">
                            {event.underlyings.map((row, index) => {
                              const isinPart =
                                showField("underlyingIsin") && row.isin ? row.isin : "";
                              const currencyPart =
                                showField("underlyingCurrency") && row.currency
                                  ? `(${row.currency})`
                                  : "";
                              const line2 = [isinPart, currencyPart].filter(Boolean).join(" ");
                              if ((!showField("underlyingName") || !row.name) && !line2) {
                                return null;
                              }
                              return (
                                <div key={`${row.isin || row.name}-${index}`} className="min-w-0 leading-snug">
                                  {showField("underlyingName") && row.name ? (
                                    <p className="truncate text-[12px] text-foreground/85">{row.name}</p>
                                  ) : null}
                                  {line2 ? (
                                    <p className="truncate font-mono text-[11px] text-muted-foreground">
                                      {line2}
                                    </p>
                                  ) : null}
                                </div>
                              );
                            })}
                          </div>
                        ) : null}
                      </div>
                    </div>
                    {showField("amount") && (event.amountDisplay || event.amount) ? (
                      <p
                        className={cn(
                          "shrink-0 font-semibold text-sm tabular-nums tracking-tight sm:pl-4",
                          negative ? "text-rose-600 dark:text-rose-400" : "text-foreground",
                        )}
                      >
                        {event.amountDisplay ||
                          `${event.currency} ${event.amount.toLocaleString("en-US", { maximumFractionDigits: 2 })}`}
                      </p>
                    ) : null}
                  </button>
                );
              })
            )}
          </div>
        </div>
      ) : null}
      </ReportLoadingPanel>

      <CashflowDaySheet
        date={selectedDate}
        events={selectedDayEvents}
        open={sheetOpen}
        onOpenChange={setSheetOpen}
        detailVisibility={detailVisibility}
        detailOrder={detailOrder}
      />

      <CustomerFieldsPanel
        open={fieldsOpen}
        onOpenChange={setFieldsOpen}
        catalog={fieldsTab === "chips" ? CASHFLOW_CHIP_FIELDS_CATALOG : CASHFLOW_DETAIL_FIELDS_CATALOG}
        visibility={fieldsTab === "chips" ? chipVisibility : detailVisibility}
        order={fieldsTab === "chips" ? chipOrder : detailOrder}
        lockedKeys={[...CASHFLOW_LOCKED_KEYS]}
        groups={fieldsTab === "chips" ? CASHFLOW_CHIP_FIELD_GROUPS : undefined}
        title="Fields"
        description={
          fieldsTab === "chips"
            ? "Choose which fields appear on calendar chips and list rows. Preferences are saved for your user."
            : "Choose which fields appear in the hover detail card. The header (type, asset class, Ref ID) always stays visible."
        }
        toolbar={
          <Tabs
            value={fieldsTab}
            onValueChange={(value) => {
              if (value === "chips" || value === "details") setFieldsTab(value);
            }}
            className="w-full gap-0"
          >
            <TabsList variant="default" className="grid h-9 w-full grid-cols-2">
              <TabsTrigger value="chips">Chips</TabsTrigger>
              <TabsTrigger value="details">Details</TabsTrigger>
            </TabsList>
          </Tabs>
        }
        onToggle={fieldsTab === "chips" ? setChipFieldVisible : setDetailFieldVisible}
        onReorder={fieldsTab === "chips" ? reorderChipFields : reorderDetailFields}
        onHideAll={fieldsTab === "chips" ? hideAllChipFields : hideAllDetailFields}
      />
    </div>
  );
}
