"use client";

import * as React from "react";
import { resolveCustomerTenant } from "@/app/customer/_lib/resolve-customer-tenant";
import Link from "next/link";
import { useParams } from "next/navigation";
import { format } from "date-fns";
import {
  Activity,
  Download,
  PiggyBank,
  RefreshCw,
  Scale,
  TrendingUp,
  Wallet,
  X,
} from "lucide-react";
import { toast } from "sonner";

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { type ChartConfig } from "@/components/ui/chart";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { cn } from "@/lib/utils";

import { ReportLoadingPanel } from "@/app/customer/[tenant]/reports/_shared/components/report-loading-panel";
import { PortfolioAnalyticsChartPanel } from "@/app/customer/[tenant]/reports/portfolio-analytics/_components/portfolio-analytics-report/portfolio-analytics-charts";
import { PortfolioAnalyticsDayChangesSheet } from "@/app/customer/[tenant]/reports/portfolio-analytics/_components/portfolio-analytics-report/portfolio-analytics-day-changes-sheet";
import {
  buildChartData,
  resolvePortfolioAnalyticsSeriesColor,
} from "@/app/customer/[tenant]/reports/portfolio-analytics/_components/portfolio-analytics-report/utils";
import {
  PORTFOLIO_ANALYTICS_PRESETS,
  type PortfolioAnalyticsPreset,
} from "@/app/customer/[tenant]/reports/portfolio-analytics/_lib/portfolio-analytics-query";
import { buildAssetAllocationSummaryFromChartSeries } from "../../_lib/asset-allocation-from-report";
import { usePerformanceSummaryReport } from "../../_lib/use-performance-summary-report";
import { usePerformanceSummaryWidget } from "../../_lib/use-performance-summary-widget";
import { AssetAllocationSummaryCard } from "./asset-allocation-summary-card";
import { LoanDetailSheet } from "@/app/customer/_components/loan-detail-sheet";
import { useImpersonationScopeRefresh } from "@/app/customer/_lib/admin/use-impersonation-scope-refresh";
import { useDefaultLayout } from "@/app/customer/_lib/use-default-layout";
import {
  buildPerformanceLedgerRows,
  formatAmountField,
  formatReportValue,
  withChartMarketValue,
} from "./utils";

function humanizeKey(key: string) {
  return key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
}

function KpiCard({
  label,
  value,
  icon,
  hint,
}: {
  label: string;
  value: string;
  icon: React.ReactNode;
  hint?: string;
}) {
  return (
    <Card className="relative gap-0 overflow-hidden border-border/80 bg-card py-0 shadow-sm transition-shadow hover:shadow-md">
      <CardContent className="flex items-start justify-between gap-3 p-4 sm:p-5">
        <div className="min-w-0">
          <p className="font-medium text-[11px] text-muted-foreground uppercase tracking-[0.14em]">{label}</p>
          <p className="mt-2 truncate font-semibold text-xl tabular-nums tracking-tight leading-none sm:text-[1.35rem]">
            {value}
          </p>
          {hint ? <p className="mt-2 text-muted-foreground text-xs">{hint}</p> : null}
        </div>
        <div className="flex size-10 shrink-0 items-center justify-center rounded-2xl border bg-muted/40 text-muted-foreground">
          {icon}
        </div>
      </CardContent>
    </Card>
  );
}

function SectionShell({
  title,
  subtitle,
  icon,
  actions,
  children,
  contentClassName,
  onHeaderClick,
}: {
  title: string;
  subtitle?: string;
  icon: React.ReactNode;
  actions?: React.ReactNode;
  children: React.ReactNode;
  contentClassName?: string;
  onHeaderClick?: () => void;
}) {
  return (
    <Card className="gap-0 overflow-hidden border-border/80 py-0 shadow-sm transition-shadow hover:shadow-md">
      <div
        className={cn(
          "flex flex-wrap items-center justify-between gap-3 border-b bg-muted/20 px-4 py-3.5",
          onHeaderClick && "cursor-pointer hover:bg-muted/35",
        )}
        role={onHeaderClick ? "button" : undefined}
        tabIndex={onHeaderClick ? 0 : undefined}
        onClick={onHeaderClick}
        onKeyDown={
          onHeaderClick
            ? (event) => {
                if (event.key === "Enter" || event.key === " ") {
                  event.preventDefault();
                  onHeaderClick();
                }
              }
            : undefined
        }
      >
        <div className="flex min-w-0 items-center gap-2.5">
          <div className="flex size-9 shrink-0 items-center justify-center rounded-xl border bg-background/80">
            {icon}
          </div>
          <div className="min-w-0">
            <p className="font-semibold text-[11px] uppercase tracking-[0.14em]">{title}</p>
            {subtitle ? <p className="mt-0.5 text-muted-foreground text-xs">{subtitle}</p> : null}
          </div>
        </div>
        {actions}
      </div>
      <CardContent className={cn("p-0", contentClassName)}>{children}</CardContent>
    </Card>
  );
}

function IncomeBreakdownTable({
  rows,
  assetTypeTitle,
}: {
  rows: Array<Record<string, unknown>>;
  assetTypeTitle: Record<string, string>;
}) {
  const columns = React.useMemo(() => {
    const keys = new Set<string>();
    for (const row of rows) {
      for (const key of Object.keys(row)) keys.add(key);
    }
    return Array.from(keys);
  }, [rows]);

  if (rows.length === 0) {
    return <p className="py-10 text-center text-muted-foreground text-sm">No income entries for this period.</p>;
  }

  return (
    <div className="overflow-x-auto">
      <Table>
        <TableHeader>
          <TableRow className="bg-muted/40 hover:bg-muted/40">
            {columns.map((col) => (
              <TableHead key={col} className="h-9 text-xs">
                {humanizeKey(col)}
              </TableHead>
            ))}
          </TableRow>
        </TableHeader>
        <TableBody>
          {rows.map((row, index) => (
            <TableRow key={index} className="hover:bg-muted/25">
              {columns.map((col) => {
                const raw = row[col];
                const display =
                  (col === "asset_type" || col === "type" || col === "product_type") &&
                  typeof raw === "string" &&
                  assetTypeTitle[raw]
                    ? assetTypeTitle[raw]
                    : raw;
                return (
                  <TableCell key={col} className="text-sm">
                    {display === null || display === undefined || display === "" ? "—" : String(display)}
                  </TableCell>
                );
              })}
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </div>
  );
}

export function PerformanceSummaryView() {
  const params = useParams<{ tenant?: string }>();
  const tenant = typeof params?.tenant === "string" && params.tenant.trim() ? params.tenant.trim() : resolveCustomerTenant();

  const [refreshKey, setRefreshKey] = React.useState(0);
  const [preset, setPreset] = React.useState<PortfolioAnalyticsPreset>("1m");
  // Empty = live today (OS chart default); past day-click sets snapshot as-of.
  const [portfolioAsOf, setPortfolioAsOf] = React.useState("");
  const todayYmd = format(new Date(), "yyyy-MM-dd");
  const { layout, loading: layoutLoading } = useDefaultLayout(tenant);

  const refreshForPortfolioScope = React.useCallback(() => {
    setRefreshKey((value) => value + 1);
  }, []);
  useImpersonationScopeRefresh(refreshForPortfolioScope);

  const { data: widgetData, isLoading: widgetLoading, errorMessage: widgetError } = usePerformanceSummaryWidget(
    tenant,
    refreshKey,
    portfolioAsOf,
  );
  const { data: reportData, isLoading: reportLoading, errorMessage: reportError } = usePerformanceSummaryReport(
    tenant,
    refreshKey,
    preset,
    portfolioAsOf,
    layoutLoading ? "default" : layout,
  );
  const isLoading = widgetLoading || reportLoading;
  const errorMessage = widgetError ?? reportError;

  const series = React.useMemo(() => reportData?.serializeArra ?? [], [reportData]);
  const dateList = React.useMemo(() => reportData?.date_list ?? [], [reportData]);
  const incomeRows = React.useMemo(() => reportData?.incomeModeule ?? [], [reportData]);
  const hasChartData = series.length > 0 && dateList.length > 0;
  const hasIncomeData = incomeRows.length > 0;

  // Same chart series shape as Portfolio Analytics (values aligned to date_list).
  const apiSeries = React.useMemo(
    () =>
      series.map((s) => ({
        id: s.id,
        name: s.name,
        visible: s.visible,
        values: s.data,
      })),
    [series],
  );

  // Donut + ledger MV = same OS chart day (day-click asOf, else live today / latest point).
  const allocationSummary = React.useMemo(
    () =>
      buildAssetAllocationSummaryFromChartSeries({
        dateList,
        series: apiSeries,
        asOf: portfolioAsOf || null,
        today: todayYmd,
        reportingCurrency: reportData?.code ?? widgetData?.currency ?? "USD",
      }),
    [dateList, apiSeries, portfolioAsOf, widgetData?.currency, reportData?.code, todayYmd],
  );

  const chartAlignedWidget = React.useMemo(() => {
    if (!widgetData) return null;
    const chartMv =
      Math.abs(allocationSummary.grandTotal) > 1e-9 ? allocationSummary.grandTotal : null;
    return withChartMarketValue(widgetData, chartMv);
  }, [widgetData, allocationSummary.grandTotal]);

  const ledgerRows = React.useMemo(
    () => (chartAlignedWidget ? buildPerformanceLedgerRows(chartAlignedWidget) : []),
    [chartAlignedWidget],
  );

  const [focusedSeries, setFocusedSeries] = React.useState<string | null>("ALL");
  const [dayOpen, setDayOpen] = React.useState(false);
  const [dayDate, setDayDate] = React.useState<string | null>(null);
  const [dayPrev, setDayPrev] = React.useState<string | null>(null);
  const [changesMode, setChangesMode] = React.useState<"day" | "period">("day");
  const [dayMacro, setDayMacro] = React.useState<string | null>(null);

  const openDayBreakdown = React.useCallback(
    (date: string, previousDate: string | null, macro: string | null = null) => {
      setChangesMode("day");
      setDayDate(date);
      setDayPrev(previousDate);
      setDayMacro(macro);
      setDayOpen(true);
      setPortfolioAsOf(date < todayYmd ? date : "");
    },
    [todayYmd],
  );

  /** First → last OS snapshot in the selected 1W/1M/3M/6M chart window. */
  const periodRange = React.useMemo(() => {
    const endDate = allocationSummary.asOfDate;
    if (!endDate) return { start: null as string | null, end: null as string | null };
    const all = apiSeries.find((s) => s.id === "ALL");
    const endIndex = dateList.indexOf(endDate);
    const last = endIndex >= 0 ? endIndex : dateList.length - 1;
    let startDate: string | null = null;
    for (let i = 0; i <= last; i++) {
      if (typeof all?.values[i] === "number" && dateList[i]) {
        startDate = dateList[i];
        break;
      }
    }
    return { start: startDate, end: endDate };
  }, [allocationSummary.asOfDate, dateList, apiSeries]);

  /** Period changes for the selected 1W/1M/3M/6M window (optional macro filter). */
  const openPeriodBreakdown = React.useCallback(
    (assetClass?: string) => {
      const endDate = periodRange.end;
      const startDate = periodRange.start;
      if (!endDate) return;
      if (!startDate || startDate === endDate) {
        const all = apiSeries.find((s) => s.id === "ALL");
        const endIndex = dateList.indexOf(endDate);
        const last = endIndex >= 0 ? endIndex : dateList.length - 1;
        let previousDate: string | null = null;
        for (let i = last - 1; i >= 0; i--) {
          if (typeof all?.values[i] === "number" && dateList[i]) {
            previousDate = dateList[i];
            break;
          }
        }
        openDayBreakdown(endDate, previousDate, assetClass?.trim() || null);
        return;
      }
      setChangesMode("period");
      setDayDate(endDate);
      setDayPrev(startDate);
      setDayMacro(assetClass?.trim() || null);
      setDayOpen(true);
      setPortfolioAsOf(endDate < todayYmd ? endDate : "");
    },
    [periodRange.end, periodRange.start, dateList, apiSeries, openDayBreakdown, todayYmd],
  );

  const chartSeriesConfig = React.useMemo(
    () =>
      Object.fromEntries(
        apiSeries.map((s, index) => [
          s.id,
          {
            label: s.id === "ALL" ? "Total" : s.name,
            color: resolvePortfolioAnalyticsSeriesColor(s, index),
          },
        ]),
      ) satisfies ChartConfig,
    [apiSeries],
  );

  const visibleChartSeries = React.useMemo(() => {
    if (focusedSeries) {
      return apiSeries.filter((s) => s.id === focusedSeries).map(({ id, name }) => ({ id, name }));
    }
    return apiSeries.filter((s) => s.id !== "ALL").map(({ id, name }) => ({ id, name }));
  }, [apiSeries, focusedSeries]);

  const legendSeries = React.useMemo(
    () => apiSeries.map(({ id, name }) => ({ id, name })),
    [apiSeries],
  );

  const chartData = React.useMemo(() => buildChartData(dateList, apiSeries), [dateList, apiSeries]);

  const handleLegendClick = (seriesId: string) => {
    if (seriesId === "ALL") {
      setFocusedSeries((prev) => (prev === "ALL" ? null : "ALL"));
      return;
    }
    setFocusedSeries((prev) => (prev === seriesId ? "ALL" : seriesId));
  };

  const currency = chartAlignedWidget?.currency ?? widgetData?.currency ?? "USD";
  const asOfLabel =
    allocationSummary.asOfDate?.trim() || widgetData?.as_of?.trim() || "—";
  const [loanCurrency, setLoanCurrency] = React.useState<string | null>(null);
  const selectedLoan =
    (chartAlignedWidget ?? widgetData)?.loans.find((loan) => loan.currency === loanCurrency) ?? null;

  return (
    <div className="flex min-w-0 flex-col gap-5">
      <div className="flex flex-col gap-3 border-b pb-4 lg:flex-row lg:items-start lg:justify-between">
        <div className="min-w-0 space-y-2">
          <div className="flex flex-wrap items-center gap-2.5">
            <div className="flex size-8 items-center justify-center rounded-lg border bg-sky-500/10 text-sky-700 dark:text-sky-400">
              <Activity className="size-4" />
            </div>
            <h1 className="font-semibold text-2xl tracking-tight leading-none">Performance Summary</h1>
            {asOfLabel !== "—" ? (
              <Badge variant="secondary" className="font-normal">
                As of {asOfLabel}
              </Badge>
            ) : null}
            {isLoading ? (
              <Badge variant="outline" className="font-normal">
                Loading…
              </Badge>
            ) : null}
          </div>
          <p className="text-muted-foreground text-sm">
            Portfolio value, equity, allocation, and performance trends
          </p>
          {errorMessage ? <p className="text-destructive text-sm">{errorMessage}</p> : null}
        </div>
        <div className="flex shrink-0 flex-wrap items-center justify-end gap-2">
          <div className="inline-flex items-center rounded-lg border border-border/60 bg-muted/25 p-0.5">
            {PORTFOLIO_ANALYTICS_PRESETS.map((item) => (
              <Button
                key={item.id}
                variant="ghost"
                size="sm"
                className={cn(
                  "h-7 rounded-md px-2.5 text-xs shadow-none",
                  preset === item.id
                    ? "bg-background text-foreground shadow-sm"
                    : "text-muted-foreground hover:bg-transparent hover:text-foreground",
                )}
                onClick={() => {
                  setPreset(item.id);
                  setPortfolioAsOf("");
                }}
              >
                {item.label}
              </Button>
            ))}
          </div>
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button variant="outline" size="icon" className="size-9 shrink-0">
                <Download className="size-4" />
                <span className="sr-only">Download</span>
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end">
              <DropdownMenuItem onClick={() => toast.message("PDF export", { description: "Coming soon." })}>
                Download PDF
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
          <Button
            variant="outline"
            size="icon"
            className="size-9 shrink-0"
            disabled={isLoading}
            onClick={() => setRefreshKey((k) => k + 1)}
          >
            <RefreshCw className={cn("size-4", isLoading && "animate-spin")} />
            <span className="sr-only">Refresh</span>
          </Button>
          <Button variant="outline" size="icon" className="size-9 shrink-0" asChild>
            <Link href={`/customer/${tenant}/reports`}>
              <X className="size-4" />
              <span className="sr-only">Close</span>
            </Link>
          </Button>
        </div>
      </div>

      <ReportLoadingPanel
        loading={isLoading}
        label="Loading performance summary…"
        className={cn(isLoading && "pointer-events-none")}
      >
        <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-4">
          <KpiCard
            label="Market value"
            value={
              chartAlignedWidget ? formatAmountField(chartAlignedWidget.market_value, currency) : "—"
            }
            icon={<Wallet className="size-5" />}
            hint={asOfLabel !== "—" ? `OS chart · ${asOfLabel}` : currency}
          />
          <KpiCard
            label="Client equity"
            value={
              chartAlignedWidget ? formatAmountField(chartAlignedWidget.client_equity, currency) : "—"
            }
            icon={<Scale className="size-5" />}
            hint="After loans · OS chart"
          />
          <KpiCard
            label="Mark to market"
            value={
              chartAlignedWidget ? formatAmountField(chartAlignedWidget.mark_to_market, currency) : "—"
            }
            icon={<TrendingUp className="size-5" />}
            hint="Cost vs market · OS chart"
          />
          <KpiCard
            label="Leveraged yield"
            value={
              chartAlignedWidget
                ? formatReportValue(chartAlignedWidget.leveraged_yield?.fmt)
                : "—"
            }
            icon={<PiggyBank className="size-5" />}
            hint="Net income / equity"
          />
        </div>

        <div className="mt-5 grid grid-cols-1 items-start gap-4 lg:grid-cols-2">
          <AssetAllocationSummaryCard
            rows={allocationSummary.rows}
            grandTotal={allocationSummary.grandTotal}
            reportingCurrency={allocationSummary.reportingCurrency}
            isLoading={reportLoading || layoutLoading}
            errorMessage={reportError && !reportData ? reportError : null}
            onOpenBreakdown={
              allocationSummary.asOfDate ? openPeriodBreakdown : undefined
            }
            layoutLabel={
              allocationSummary.asOfDate
                ? `OS chart · ${allocationSummary.asOfDate}`
                : layout === "macro"
                  ? "by Macro"
                  : layout === "bridge"
                    ? "by Bridge"
                    : "by Asset Class"
            }
          />

          <SectionShell
            title="Performance ledger"
            subtitle={
              allocationSummary.asOfDate
                ? `Amounts in ${currency} · OS chart · ${allocationSummary.asOfDate} · Click for period changes`
                : `Amounts in ${currency}`
            }
            icon={<Activity className="size-4 text-muted-foreground" />}
            onHeaderClick={
              allocationSummary.asOfDate ? () => openPeriodBreakdown() : undefined
            }
          >
            {ledgerRows.length === 0 ? (
              <p className="py-16 text-center text-muted-foreground text-sm">
                No performance figures are available for this account yet.
              </p>
            ) : (
              <Table>
                <TableHeader>
                  <TableRow className="bg-muted/40 hover:bg-muted/40">
                    <TableHead className="h-9 w-10 text-center text-xs">#</TableHead>
                    <TableHead className="h-9 text-xs">Item</TableHead>
                    <TableHead className="h-9 pr-4 text-right text-xs">Amount</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {ledgerRows.map((row) => {
                    if (row.kind === "spacer") {
                      return (
                        <TableRow key={row.id} className="h-2 hover:bg-transparent">
                          <TableCell colSpan={3} className="p-0" />
                        </TableRow>
                      );
                    }
                    return (
                      <TableRow
                        key={row.id}
                        onClick={
                          row.loanCurrency
                            ? () => setLoanCurrency(row.loanCurrency ?? null)
                            : allocationSummary.asOfDate
                              ? () => openPeriodBreakdown()
                              : undefined
                        }
                        className={cn(
                          "hover:bg-muted/25",
                          row.kind === "subtotal" && "bg-muted/30 font-semibold",
                          row.kind === "total" && "bg-muted/50 font-semibold",
                          (row.loanCurrency || allocationSummary.asOfDate) && "cursor-pointer",
                        )}
                      >
                        <TableCell className="text-center text-muted-foreground text-xs tabular-nums">
                          {row.index}
                        </TableCell>
                        <TableCell
                          className={cn(
                            "text-sm",
                            row.loanCurrency && "text-primary underline-offset-2 hover:underline",
                          )}
                        >
                          {row.label}
                          {row.hint ? (
                            <span className="block text-xs font-normal text-muted-foreground">{row.hint}</span>
                          ) : null}
                        </TableCell>
                        <TableCell className="pr-4 text-right text-sm tabular-nums">{row.value ?? "—"}</TableCell>
                      </TableRow>
                    );
                  })}
                </TableBody>
              </Table>
            )}
            <LoanDetailSheet
              loan={selectedLoan}
              reportingCurrency={currency}
              asOf={periodRange.end || allocationSummary.asOfDate || widgetData?.as_of}
              periodStart={periodRange.start}
              tenant={tenant}
              onClose={() => setLoanCurrency(null)}
            />
          </SectionShell>
        </div>

        {hasChartData ? (
          <div className="mt-5">
            <PortfolioAnalyticsChartPanel
              isLoading={reportLoading}
              chartData={chartData}
              chartSeriesConfig={chartSeriesConfig}
              visibleChartSeries={visibleChartSeries}
              legendSeries={legendSeries}
              focusedSeries={focusedSeries}
              onLegendClick={handleLegendClick}
              onClearFocus={() => setFocusedSeries("ALL")}
              onDayClick={(date, previousDate) => openDayBreakdown(date, previousDate, null)}
              onPeriodChangesClick={(endDate, startDate) => {
                setChangesMode("period");
                setDayDate(endDate);
                setDayPrev(startDate);
                setDayMacro(null);
                setDayOpen(true);
                setPortfolioAsOf(endDate < todayYmd ? endDate : "");
              }}
              emptyLabel="No OS as-of snapshots in this range"
            />
          </div>
        ) : null}

        <PortfolioAnalyticsDayChangesSheet
          tenant={tenant}
          date={dayDate}
          previousDate={dayPrev}
          bankQuery=""
          mode={changesMode}
          open={dayOpen}
          onOpenChange={setDayOpen}
          initialMacro={dayMacro}
        />

        {hasIncomeData ? (
          <div className="mt-5">
            <SectionShell
              title="Income breakdown"
              subtitle={`${incomeRows.length} entries`}
              icon={<PiggyBank className="size-4 text-muted-foreground" />}
            >
              <IncomeBreakdownTable rows={incomeRows} assetTypeTitle={reportData?.asset_type_title ?? {}} />
            </SectionShell>
          </div>
        ) : null}
      </ReportLoadingPanel>
    </div>
  );
}
