"use client";

import * as React from "react";
import Link from "next/link";
import { format, parseISO } from "date-fns";
import {
  ArrowDownUp,
  Building2,
  ChevronDown,
  ChevronsDownUp,
  Download,
  Globe,
  Layers,
  LayoutGrid,
  MapPin,
  Printer,
  RefreshCw,
  Tag,
  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 {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from "@/components/ui/collapsible";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { cn } from "@/lib/utils";

import { ReportLoadingPanel } from "@/app/customer/[tenant]/reports/_shared/components/report-loading-panel";
import { useBankWiseAumList } from "../../_lib/use-bank-wise-aum-list";
import { BankWiseAumFiltersDialog } from "./bank-wise-aum-filters-dialog";
import {
  type BankAumBreakdownTab,
  type BankAumMetricRow,
  type BankAumSummary,
  type BankWiseAumFilters,
  bankWiseAumMeta,
  defaultBankWiseAumFilters,
  hasActiveBankWiseAumFilters,
  isCompareMode,
} from "./schema";
import { useImpersonationScopeRefresh } from "@/app/customer/_lib/admin/use-impersonation-scope-refresh";
import {
  computeDiff,
  computeGrandTotals,
  filterBanks,
  formatDiff,
  formatDiffPct,
  formatMoney,
  formatPeriodLabel,
  formatPlain,
  sortBanksByAum,
  sumMetrics,
} from "./utils";

const innerTabs: { id: BankAumBreakdownTab; label: string; icon: React.ReactNode }[] = [
  { id: "assetClass", label: "Asset class", icon: <LayoutGrid className="size-3.5" /> },
  { id: "assetType", label: "Asset type", icon: <Tag className="size-3.5" /> },
  { id: "sector", label: "Sector", icon: <Layers className="size-3.5" /> },
  { id: "geography", label: "Geography", icon: <Globe className="size-3.5" /> },
];

function pnlClass(value: number) {
  if (value > 0) return "text-emerald-600 dark:text-emerald-400 font-semibold";
  if (value < 0) return "text-red-600 dark:text-red-400 font-semibold";
  return "text-muted-foreground";
}

function BreakdownTable({
  rows,
  compare,
  labelFrom,
  labelTo,
  nameHeader,
}: {
  rows: BankAumMetricRow[];
  compare: boolean;
  labelFrom: string;
  labelTo: string;
  nameHeader: string;
}) {
  const totals = sumMetrics(rows);

  return (
    <div className="overflow-x-auto rounded-lg border border-border/80">
      <Table>
        <TableHeader>
          <TableRow className="bg-slate-800 hover:bg-slate-800">
            <TableHead className="min-w-[200px] text-white">{nameHeader}</TableHead>
            {compare ? (
              <>
                <TableHead className="bg-violet-900/80 text-right text-violet-200 text-xs">{labelFrom}</TableHead>
                <TableHead className="bg-emerald-900/80 text-right text-emerald-200 text-xs">{labelTo}</TableHead>
                <TableHead className="bg-slate-700 text-right text-slate-200 text-xs">Change</TableHead>
                <TableHead className="bg-slate-700 text-right text-slate-200 text-xs">% Chg</TableHead>
              </>
            ) : (
              <>
                <TableHead className="text-right text-white text-xs">Purchase value</TableHead>
                <TableHead className="bg-emerald-900/50 text-right text-emerald-100 text-xs">
                  Market value (AUM)
                  {labelTo !== "Current" ? ` · ${labelTo}` : ""}
                </TableHead>
              </>
            )}
          </TableRow>
        </TableHeader>
        <TableBody>
          {rows.length === 0 ? (
            <TableRow>
              <TableCell colSpan={compare ? 5 : 3} className="py-10 text-center text-muted-foreground text-sm">
                No data for this breakdown
              </TableCell>
            </TableRow>
          ) : (
            rows.map((row) => {
              const diff = computeDiff(row.d1Aum, row.d2Aum);
              return (
                <TableRow key={row.id} className="even:bg-muted/30">
                  <TableCell className="py-2.5 font-medium text-sm">
                    {row.label}
                    {row.sublabel ? (
                      <Badge variant="outline" className="ml-2 font-normal text-[10px]">
                        {row.sublabel}
                      </Badge>
                    ) : null}
                  </TableCell>
                  {compare ? (
                    <>
                      <TableCell className="py-2.5 text-right text-sm tabular-nums">{formatMoney(row.d1Aum)}</TableCell>
                      <TableCell className="py-2.5 text-right text-sm tabular-nums">{formatMoney(row.d2Aum)}</TableCell>
                      <TableCell className={cn("bg-muted/40 py-2.5 text-right text-sm tabular-nums", pnlClass(diff))}>
                        {formatDiff(diff)}
                      </TableCell>
                      <TableCell className={cn("bg-muted/40 py-2.5 text-right text-sm tabular-nums", pnlClass(diff))}>
                        {formatDiffPct(row.d1Aum, row.d2Aum)}
                      </TableCell>
                    </>
                  ) : (
                    <>
                      <TableCell className="py-2.5 text-right text-sm tabular-nums">{formatMoney(row.d2Pv)}</TableCell>
                      <TableCell className="py-2.5 text-right text-sm tabular-nums">{formatMoney(row.d2Aum)}</TableCell>
                    </>
                  )}
                </TableRow>
              );
            })
          )}
          {rows.length > 0 ? (
            <TableRow className="border-t-2 bg-gradient-to-r from-slate-800 to-slate-700 font-semibold hover:from-slate-800 hover:to-slate-700">
              <TableCell className="py-3 text-white">Total AUM</TableCell>
              {compare ? (
                <>
                  <TableCell className="py-3 text-right text-white tabular-nums">{formatMoney(totals.d1Aum)}</TableCell>
                  <TableCell className="py-3 text-right text-white tabular-nums">{formatMoney(totals.d2Aum)}</TableCell>
                  <TableCell className={cn("py-3 text-right tabular-nums", totals.d2Aum - totals.d1Aum >= 0 ? "text-emerald-300" : "text-red-300")}>
                    {formatDiff(computeDiff(totals.d1Aum, totals.d2Aum))}
                  </TableCell>
                  <TableCell className={cn("py-3 text-right tabular-nums", totals.d2Aum - totals.d1Aum >= 0 ? "text-emerald-300" : "text-red-300")}>
                    {formatDiffPct(totals.d1Aum, totals.d2Aum)}
                  </TableCell>
                </>
              ) : (
                <>
                  <TableCell className="py-3 text-right text-white tabular-nums">{formatMoney(totals.d2Pv)}</TableCell>
                  <TableCell className="py-3 text-right text-white tabular-nums">{formatMoney(totals.d2Aum)}</TableCell>
                </>
              )}
            </TableRow>
          ) : null}
        </TableBody>
      </Table>
    </div>
  );
}

function BankAccordion({
  bank,
  compare,
  labelFrom,
  labelTo,
  totalAum,
  open,
  onOpenChange,
}: {
  bank: BankAumSummary;
  compare: boolean;
  labelFrom: string;
  labelTo: string;
  totalAum: number;
  open: boolean;
  onOpenChange: (open: boolean) => void;
}) {
  const diff = computeDiff(bank.d1Aum, bank.d2Aum);
  const diffPct = formatDiffPct(bank.d1Aum, bank.d2Aum);
  const pctOfTotal = totalAum > 0 ? (bank.d2Aum / totalAum) * 100 : 0;

  const rowsForTab = (tab: BankAumBreakdownTab): BankAumMetricRow[] => {
    switch (tab) {
      case "assetClass":
        return bank.assetClassRows;
      case "assetType":
        return bank.assetTypeRows;
      case "sector":
        return bank.sectorRows;
      case "geography":
        return bank.geographyRows;
    }
  };

  const nameForTab = (tab: BankAumBreakdownTab) => {
    switch (tab) {
      case "assetClass":
        return "Asset class";
      case "assetType":
        return "Asset type";
      case "sector":
        return "Sector";
      case "geography":
        return "Country";
    }
  };

  return (
    <Collapsible open={open} onOpenChange={onOpenChange}>
      <Card
        className={cn(
          "overflow-hidden border-border/80 py-0 shadow-sm transition-shadow",
          open && "shadow-md ring-1 ring-primary/15",
        )}
      >
        <CollapsibleTrigger asChild>
          <button
            type="button"
            className="flex w-full items-center gap-4 px-4 py-4 text-left transition-colors hover:bg-muted/40"
          >
            <div
              className="flex size-10 shrink-0 items-center justify-center rounded-xl"
              style={{
                backgroundColor: `color-mix(in srgb, ${bank.accentColor} 18%, transparent)`,
                color: bank.accentColor,
              }}
            >
              <Building2 className="size-5" />
            </div>
            <div className="min-w-0 flex-1">
              <p className="font-semibold text-base leading-tight">{bank.bankName}</p>
              <p className="mt-0.5 text-muted-foreground text-xs">
                {bank.reportingCurrency}
                <span className="mx-1.5 text-border">·</span>
                {bank.assetClassRows.length} asset classes
                <span className="mx-1.5 text-border">·</span>
                {bank.assetTypeRows.length} types
                <span className="mx-1.5 text-border">·</span>
                {bank.sectorRows.length} sectors
                <span className="mx-1.5 text-border">·</span>
                {bank.geographyRows.length} countries
              </p>
            </div>
            <div className="hidden shrink-0 items-center gap-6 sm:flex">
              {compare ? (
                <>
                  <div className="text-right">
                    <p className="text-[10px] font-bold text-muted-foreground uppercase tracking-wide">{labelFrom}</p>
                    <p className="mt-0.5 text-sm tabular-nums">{formatPlain(bank.d1Aum, 0)}</p>
                  </div>
                  <div className="text-right">
                    <p className="text-[10px] font-bold text-muted-foreground uppercase tracking-wide">Change</p>
                    <p className={cn("mt-0.5 text-sm tabular-nums", pnlClass(diff))}>{formatDiff(diff)}</p>
                    <p className={cn("text-[11px] tabular-nums", pnlClass(diff))}>{diffPct}</p>
                  </div>
                </>
              ) : null}
              <div className="text-right">
                <p className="text-[10px] font-bold text-muted-foreground uppercase tracking-wide">
                  AUM ({bank.reportingCurrency})
                </p>
                <p className="mt-0.5 font-bold text-base tabular-nums">{formatPlain(bank.d2Aum, 0)}</p>
                <p className="text-muted-foreground text-[11px]">{pctOfTotal.toFixed(1)}% of total</p>
              </div>
              <div className="w-20">
                <p className="mb-1 text-right text-[10px] font-bold text-muted-foreground uppercase tracking-wide">Share</p>
                <div className="h-1.5 overflow-hidden rounded-full bg-muted">
                  <div
                    className="h-full rounded-full transition-all"
                    style={{ width: `${Math.min(pctOfTotal, 100)}%`, backgroundColor: bank.accentColor }}
                  />
                </div>
              </div>
            </div>
            <ChevronDown className={cn("size-5 shrink-0 text-muted-foreground transition-transform", open && "rotate-180")} />
          </button>
        </CollapsibleTrigger>
        <CollapsibleContent>
          <div className="border-t bg-muted/10 px-4 pb-4 pt-3">
            <Tabs defaultValue="assetClass">
              <TabsList className="h-9 w-full justify-start overflow-x-auto bg-background/80">
                {innerTabs.map((tab) => {
                  const count = rowsForTab(tab.id).length;
                  return (
                    <TabsTrigger key={tab.id} value={tab.id} className="gap-1.5 text-xs">
                      {tab.icon}
                      {tab.label}
                      <Badge variant="secondary" className="h-5 min-w-5 px-1 font-normal text-[10px] tabular-nums">
                        {count}
                      </Badge>
                    </TabsTrigger>
                  );
                })}
              </TabsList>
              {innerTabs.map((tab) => (
                <TabsContent key={tab.id} value={tab.id} className="mt-3">
                  <BreakdownTable
                    rows={rowsForTab(tab.id)}
                    compare={compare}
                    labelFrom={labelFrom}
                    labelTo={labelTo}
                    nameHeader={nameForTab(tab.id)}
                  />
                </TabsContent>
              ))}
            </Tabs>
          </div>
        </CollapsibleContent>
      </Card>
    </Collapsible>
  );
}

function formatFilterDateLabel(value: string, fallback: string) {
  if (!value.trim()) return fallback;
  try {
    return format(parseISO(value), "dd MMM yyyy");
  } catch {
    return value;
  }
}

export function BankWiseAumView() {
  const [filters, setFilters] = React.useState<BankWiseAumFilters>(defaultBankWiseAumFilters);
  const [openBanks, setOpenBanks] = React.useState<Record<string, boolean>>({});
  const [refreshKey, setRefreshKey] = React.useState(0);

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


  const {
    banks,
    users,
    bankOptions,
    assetClassOptions,
    sectorOptions,
    countryOptions,
    label1: apiLabel1,
    label2: apiLabel2,
    reportingCurrency,
    isLoading,
    errorMessage,
  } = useBankWiseAumList(filters, refreshKey);

  const meta = bankWiseAumMeta;
  const effectiveFilters = React.useMemo(
    () => ({
      ...filters,
      banks: filters.banks.length > 0 ? filters.banks : bankOptions,
    }),
    [filters, bankOptions],
  );
  const filteredBanks = React.useMemo(
    () => sortBanksByAum(filterBanks(banks, effectiveFilters, bankOptions)),
    [banks, effectiveFilters, bankOptions],
  );
  const grand = React.useMemo(() => computeGrandTotals(filteredBanks), [filteredBanks]);
  const hasActiveFilters = hasActiveBankWiseAumFilters(effectiveFilters, bankOptions);
  const compare = isCompareMode(filters);

  const labelFrom = apiLabel1 || formatFilterDateLabel(filters.dateFrom, "Period 1");
  const labelTo = apiLabel2 || formatFilterDateLabel(filters.dateTo, "Current");
  const snapshotLabel = labelTo;

  const expandAll = () => {
    const next: Record<string, boolean> = {};
    for (const b of filteredBanks) next[b.id] = true;
    setOpenBanks(next);
  };

  const collapseAll = () => setOpenBanks({});

  const toggleBank = (id: string, open: boolean) => {
    setOpenBanks((p) => ({ ...p, [id]: open }));
  };

  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">
              <Building2 className="size-4" />
            </div>
            <h1 className="font-semibold text-2xl tracking-tight leading-none">{meta.title}</h1>
            <Badge variant="secondary" className="font-normal tabular-nums">
              {filteredBanks.length} banks
            </Badge>
          </div>
          <p className="text-muted-foreground text-sm">
            {meta.subtitle}
            {hasActiveFilters ? " · filtered" : ""}
          </p>
          {errorMessage ? <p className="text-destructive text-sm">{errorMessage}</p> : null}
        </div>
        <div className="flex shrink-0 items-center gap-2">
          <BankWiseAumFiltersDialog
            filters={effectiveFilters}
            userOptions={users}
            bankOptions={bankOptions}
            assetClassOptions={assetClassOptions}
            sectorOptions={sectorOptions}
            countryOptions={countryOptions}
            onApply={setFilters}
          />
          <Button variant="outline" size="icon" className="size-9 shrink-0" onClick={() => window.print()}>
            <Printer className="size-4" />
            <span className="sr-only">Print</span>
          </Button>
          <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("Excel export", { description: "Coming soon." })}>
                Download Excel
              </DropdownMenuItem>
              <DropdownMenuItem onClick={() => toast.message("CSV export", { description: "Coming soon." })}>
                Download CSV
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
          <Button
            variant="outline"
            size="icon"
            className="size-9 shrink-0"
            disabled={isLoading}
            onClick={() => {
              setRefreshKey((k) => k + 1);
              toast.success("Report refreshed");
            }}
          >
            <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/reports">
              <X className="size-4" />
              <span className="sr-only">Close</span>
            </Link>
          </Button>
        </div>
      </div>

      <div className="flex flex-wrap items-center gap-2 rounded-lg border border-sky-500/20 bg-sky-500/5 px-4 py-2.5 text-sm">
        <MapPin className="size-4 text-sky-600 dark:text-sky-400" />
        <span className="font-medium text-foreground">{formatPeriodLabel(filters)}</span>
        <span className="text-muted-foreground">·</span>
        <span className="text-muted-foreground">Generated {format(new Date(), "dd MMM yyyy, HH:mm")}</span>
        {compare ? (
          <>
            <span className="text-muted-foreground">·</span>
            <span className="inline-flex items-center gap-1 text-sky-700 text-xs dark:text-sky-400">
              <ArrowDownUp className="size-3.5" />
              Compare mode
            </span>
          </>
        ) : (
          <>
            <span className="text-muted-foreground">·</span>
            <span className="text-sky-700 text-xs dark:text-sky-400">Snapshot view</span>
          </>
        )}
      </div>

      <div className="overflow-hidden rounded-xl bg-gradient-to-br from-slate-800 via-slate-700 to-slate-800 text-white shadow-lg">
        <div className="flex flex-wrap items-center gap-4 px-5 py-4">
          <div>
            <p className="text-[11px] font-bold text-white/60 uppercase tracking-wider">Total AUM</p>
            <p className="mt-1 font-bold text-2xl tabular-nums tracking-tight">{formatMoney(grand.d2Aum)}</p>
            <p className="mt-0.5 text-sm text-white/75">
              {grand.bankCount} banks · {reportingCurrency} equivalent
            </p>
          </div>
          {compare ? (
            <>
              <div className="hidden h-12 w-px bg-white/15 sm:block" />
              <div>
                <p className="text-[11px] font-bold text-white/60 uppercase tracking-wider">{labelFrom}</p>
                <p className="mt-1 font-semibold text-lg tabular-nums">{formatMoney(grand.d1Aum)}</p>
              </div>
              <div className="hidden h-12 w-px bg-white/15 sm:block" />
              <div>
                <p className="text-[11px] font-bold text-white/60 uppercase tracking-wider">Net change</p>
                <p className={cn("mt-1 font-semibold text-lg tabular-nums", grand.diff >= 0 ? "text-emerald-300" : "text-red-300")}>
                  {formatDiff(grand.diff)}
                </p>
                <p className={cn("text-sm tabular-nums", grand.diff >= 0 ? "text-emerald-300/90" : "text-red-300/90")}>
                  {grand.diffPct === null ? "New" : formatDiffPct(grand.d1Aum, grand.d2Aum)}
                </p>
              </div>
            </>
          ) : (
            <>
              <div className="hidden h-12 w-px bg-white/15 sm:block" />
              <div>
                <p className="text-[11px] font-bold text-white/60 uppercase tracking-wider">Purchase value</p>
                <p className="mt-1 font-semibold text-lg tabular-nums">{formatMoney(grand.d2Pv)}</p>
              </div>
            </>
          )}
          <div className="ml-auto flex gap-2 print:hidden">
            <Button
              type="button"
              variant="secondary"
              size="sm"
              className="h-8 border-white/20 bg-white/10 text-white hover:bg-white/20"
              onClick={expandAll}
            >
              <ChevronsDownUp className="size-3.5" />
              Expand all
            </Button>
            <Button
              type="button"
              variant="secondary"
              size="sm"
              className="h-8 border-white/20 bg-white/10 text-white hover:bg-white/20"
              onClick={collapseAll}
            >
              Collapse all
            </Button>
          </div>
        </div>
      </div>

      <ReportLoadingPanel
        loading={isLoading}
        label="Loading bank-wise AUM…"
        className={cn(isLoading && "pointer-events-none")}
      >
        {filteredBanks.length === 0 ? (
          !isLoading ? (
            <Card className="border-dashed">
              <CardContent className="py-16 text-center text-muted-foreground">
                <Building2 className="mx-auto mb-3 size-10 opacity-40" />
                <p className="font-medium">No data found</p>
                <p className="mt-1 text-sm">Adjust filters or date range and try again.</p>
              </CardContent>
            </Card>
          ) : (
            <div className="h-full min-h-[calc(100vh-280px)]" aria-hidden />
          )
        ) : (
          <div className="flex flex-col gap-3">
          {filteredBanks.map((bank) => (
            <BankAccordion
              key={bank.id}
              bank={bank}
              compare={compare}
              labelFrom={labelFrom}
              labelTo={compare ? labelTo : snapshotLabel}
              totalAum={grand.d2Aum}
              open={!!openBanks[bank.id]}
              onOpenChange={(open) => toggleBank(bank.id, open)}
            />
          ))}
        </div>
        )}
      </ReportLoadingPanel>
    </div>
  );
}
