"use client";

import * as React from "react";
import { ArrowLeftRight, Loader2, Search, TrendingDown, X } from "lucide-react";

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetTitle,
} from "@/components/ui/sheet";
import { cn } from "@/lib/utils";
import { FiguresMaskedContext } from "@/app/customer/_components/dashboard-overview-layout";
import {
  SortableTh,
  StickyTableScroll,
  useTableSort,
} from "@/app/customer/[tenant]/reports/_shared/components/sortable-table";
import { fetchPerformanceSummaryWidgetClient } from "@/app/customer/[tenant]/reports/performance-summary/_lib/performance-summary-api";
import type {
  PerformanceSummaryLoan,
  PerformanceSummaryLoanDetail,
} from "@/app/customer/[tenant]/reports/performance-summary/_lib/performance-summary-types";
import { formatCompact } from "@/app/customer/[tenant]/reports/portfolio-analytics/_components/portfolio-analytics-report/utils";

const NO_LOAN_DETAILS: PerformanceSummaryLoanDetail[] = [];

type ChangeKind = "Opened" | "Closed" | "Changed";
type TabId = "all" | "opened" | "closed" | "changed";

type LoanChangeRow = {
  kind: ChangeKind;
  bank: string;
  customer: string;
  amountBefore: number | null;
  amountAfter: number | null;
  amountDelta: number;
};

const LOAN_SORT_ACCESSORS = {
  bank: (row: PerformanceSummaryLoanDetail) => row.bank,
  customer: (row: PerformanceSummaryLoanDetail) => row.customer,
  amount: (row: PerformanceSummaryLoanDetail) => row.amount,
};

const CHANGE_SORT_ACCESSORS = {
  kind: (row: LoanChangeRow) => row.kind,
  bank: (row: LoanChangeRow) => row.bank,
  customer: (row: LoanChangeRow) => row.customer,
  amountDelta: (row: LoanChangeRow) => row.amountDelta,
};

function InfoChip({
  label,
  value,
  detail,
}: {
  label: string;
  value: string;
  detail?: string;
}) {
  return (
    <div className="min-w-0 rounded-xl border border-border/60 bg-card/80 px-3 py-2 shadow-sm backdrop-blur-sm">
      <p className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground">{label}</p>
      <p className="mt-0.5 truncate font-medium text-foreground text-sm" title={value}>
        {value}
      </p>
      {detail ? (
        <p className="mt-0.5 truncate text-muted-foreground text-xs" title={detail}>
          {detail}
        </p>
      ) : null}
    </div>
  );
}

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

function loanLineKey(row: { bank: string; customer: string }) {
  return `${row.bank.trim().toLowerCase()}|${row.customer.trim().toLowerCase()}`;
}

function formatSignedAmount(value: number, currency: string, masked: boolean) {
  if (masked) return "*******";
  const abs = Math.abs(value);
  const body =
    abs >= 1_000_000
      ? formatCompact(value)
      : value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  if (value > 0) return `${currency} +${body.replace(/^-/, "")}`;
  if (value < 0) return `${currency} ${body.startsWith("-") ? body : `−${body}`}`;
  return `${currency} ${body}`;
}

function formatAmountPath(
  before: number | null,
  after: number | null,
  currency: string,
  masked: boolean,
) {
  if (masked) return "*******";
  const fmt = (n: number) =>
    n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  if (before != null && after != null) return `${fmt(before)} → ${fmt(after)}`;
  if (after != null) return fmt(after);
  if (before != null) return fmt(before);
  return "—";
}

/** Diff loan lines at period start vs end — same open/close/changed idea as Analytics period changes. */
export function diffLoanDetails(
  start: PerformanceSummaryLoanDetail[],
  end: PerformanceSummaryLoanDetail[],
): LoanChangeRow[] {
  const before = new Map<string, PerformanceSummaryLoanDetail>();
  for (const row of start) before.set(loanLineKey(row), row);
  const after = new Map<string, PerformanceSummaryLoanDetail>();
  for (const row of end) after.set(loanLineKey(row), row);

  const rows: LoanChangeRow[] = [];
  for (const [key, row] of after) {
    const prev = before.get(key);
    if (!prev) {
      rows.push({
        kind: "Opened",
        bank: row.bank,
        customer: row.customer,
        amountBefore: null,
        amountAfter: row.amount,
        amountDelta: row.amount,
      });
      continue;
    }
    const delta = row.amount - prev.amount;
    if (Math.abs(delta) < 1e-6) continue;
    rows.push({
      kind: "Changed",
      bank: row.bank,
      customer: row.customer,
      amountBefore: prev.amount,
      amountAfter: row.amount,
      amountDelta: delta,
    });
  }
  for (const [key, row] of before) {
    if (after.has(key)) continue;
    rows.push({
      kind: "Closed",
      bank: row.bank,
      customer: row.customer,
      amountBefore: row.amount,
      amountAfter: null,
      amountDelta: -row.amount,
    });
  }
  rows.sort((a, b) => Math.abs(b.amountDelta) - Math.abs(a.amountDelta));
  return rows;
}

export function LoanDetailSheet({
  loan,
  reportingCurrency,
  asOf,
  periodStart,
  tenant,
  onClose,
}: {
  loan: PerformanceSummaryLoan | null;
  reportingCurrency: string;
  asOf?: string;
  /** First OS snapshot in the selected 1W/1M/3M/6M range. */
  periodStart?: string | null;
  tenant?: string;
  onClose: () => void;
}) {
  const figuresMasked = React.useContext(FiguresMaskedContext);
  const open = loan != null;
  const currency = loan?.currency ?? "";
  const endDetails = loan?.details ?? NO_LOAN_DETAILS;
  const showPeriod =
    Boolean(tenant?.trim()) &&
    Boolean(periodStart?.trim()) &&
    Boolean(asOf?.trim()) &&
    periodStart!.trim() !== asOf!.trim();

  const [tab, setTab] = React.useState<TabId>("all");
  const [search, setSearch] = React.useState("");
  const [startLoading, setStartLoading] = React.useState(false);
  const [startError, setStartError] = React.useState<string | null>(null);
  const [startDetails, setStartDetails] = React.useState<PerformanceSummaryLoanDetail[]>([]);
  const [startTotal, setStartTotal] = React.useState<number | null>(null);

  React.useEffect(() => {
    if (!open) return;
    setTab("all");
    setSearch("");
  }, [open, currency]);

  React.useEffect(() => {
    if (!open || !showPeriod || !tenant?.trim() || !periodStart?.trim() || !currency) {
      setStartDetails([]);
      setStartTotal(null);
      setStartError(null);
      setStartLoading(false);
      return;
    }
    let cancelled = false;
    setStartLoading(true);
    setStartError(null);
    void fetchPerformanceSummaryWidgetClient(tenant, { asOf: periodStart.trim() })
      .then((result) => {
        if (cancelled) return;
        if (result.errorMessage || !result.data) {
          setStartError(result.errorMessage ?? "Could not load period-start loans.");
          setStartDetails([]);
          setStartTotal(null);
          return;
        }
        const startLoan = result.data.loans.find((item) => item.currency === currency);
        setStartDetails(startLoan?.details ?? []);
        setStartTotal(startLoan?.amount ?? 0);
      })
      .catch((err: unknown) => {
        if (cancelled) return;
        setStartError(err instanceof Error ? err.message : "Could not load period-start loans.");
        setStartDetails([]);
        setStartTotal(null);
      })
      .finally(() => {
        if (!cancelled) setStartLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [open, showPeriod, tenant, periodStart, currency]);

  const changeRows = React.useMemo(
    () => (showPeriod ? diffLoanDetails(startDetails, endDetails) : []),
    [showPeriod, startDetails, endDetails],
  );

  const q = search.trim().toLowerCase();
  const filteredChanges = React.useMemo(() => {
    if (!q) return changeRows;
    return changeRows.filter((row) =>
      `${row.bank} ${row.customer} ${row.kind}`.toLowerCase().includes(q),
    );
  }, [changeRows, q]);

  const opened = filteredChanges.filter((row) => row.kind === "Opened");
  const closed = filteredChanges.filter((row) => row.kind === "Closed");
  const changed = filteredChanges.filter((row) => row.kind === "Changed");
  const tabRows =
    tab === "opened" ? opened : tab === "closed" ? closed : tab === "changed" ? changed : filteredChanges;

  const { rows: sortedChanges, toggle: toggleChange, directionFor: changeDir } = useTableSort(
    tabRows,
    CHANGE_SORT_ACCESSORS,
  );
  const { rows: staticDetails, toggle, directionFor } = useTableSort(endDetails, LOAN_SORT_ACCESSORS);
  const showCustomer = (showPeriod ? changeRows : endDetails).some((row) => row.customer.trim() !== "");

  const money = (formatted: string) => (figuresMasked ? "*******" : `${reportingCurrency} ${formatted}`);
  const endTotal = loan?.amount ?? 0;
  const totalDelta =
    startTotal != null && Number.isFinite(startTotal) ? endTotal - startTotal : endTotal;

  return (
    <Sheet open={open} onOpenChange={(next) => !next && onClose()}>
      <SheetContent
        side="right"
        showCloseButton={false}
        className={cn(
          "flex h-dvh w-full flex-col gap-0 overflow-hidden bg-muted/30 p-0",
          "data-[side=right]:w-full data-[side=right]:sm:max-w-none",
          "data-[side=right]:sm:!w-[min(72rem,calc(100vw-1.5rem))]",
        )}
      >
        <div className="shrink-0 space-y-2 border-b border-border/60 bg-card/80 px-4 pt-4 pb-3 backdrop-blur-md">
          <p className="text-muted-foreground text-[10px] font-semibold tracking-widest uppercase">
            {showPeriod ? "Analytics" : "Loan details"}
          </p>
          <div className="flex items-center justify-between gap-2">
            <SheetTitle className="flex min-w-0 items-center gap-2 text-left text-base font-semibold tracking-tight">
              <span className="flex size-8 shrink-0 items-center justify-center rounded-xl bg-primary text-primary-foreground shadow-md shadow-primary/25">
                {showPeriod ? (
                  <ArrowLeftRight className="size-3.5" />
                ) : (
                  <TrendingDown className="size-3.5" />
                )}
              </span>
              <span className="truncate">
                {showPeriod ? "Period changes" : `Loan (${currency})`}
                {showPeriod ? ` · Loan (${currency})` : ""}
              </span>
            </SheetTitle>
            <Button
              type="button"
              variant="ghost"
              size="icon-sm"
              className="rounded-lg"
              onClick={onClose}
              aria-label="Close"
            >
              <X className="size-4" />
            </Button>
          </div>
          <SheetDescription className="sr-only">
            {showPeriod
              ? "Loan line opens, closes and amount changes across the selected period."
              : "Loan lines by bank for the selected currency."}
          </SheetDescription>
        </div>

        <div className="flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto px-4 py-4">
          {showPeriod ? (
            <>
              <section className="flex flex-col gap-3 rounded-2xl border border-border/60 bg-card p-3 shadow-sm">
                <div className="grid gap-2 sm:grid-cols-3">
                  <InfoChip label="Period end" value={asOf!.trim()} />
                  <InfoChip
                    label="Period start"
                    value={periodStart!.trim()}
                    detail="First snapshot in range"
                  />
                  <InfoChip
                    label="Changes"
                    value={startLoading ? "…" : String(filteredChanges.length)}
                    detail={q ? "Matching search" : "Opened · closed · changed"}
                  />
                </div>

                <div className="grid gap-2 sm:grid-cols-3">
                  <InfoChip label="Loan currency" value={currency || "—"} />
                  <InfoChip
                    label="Total (end)"
                    value={loan ? money(loan.formatted) : "—"}
                  />
                  <InfoChip
                    label="Total Δ"
                    value={
                      startLoading
                        ? "…"
                        : formatSignedAmount(totalDelta, reportingCurrency, figuresMasked)
                    }
                    detail={
                      startTotal != null
                        ? `${formatSignedAmount(startTotal, reportingCurrency, figuresMasked)} → ${loan ? money(loan.formatted) : "—"}`
                        : undefined
                    }
                  />
                </div>

                <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                  <div
                    className="inline-flex w-fit flex-wrap gap-0.5 rounded-lg border border-border/60 bg-muted/40 p-1"
                    role="tablist"
                    aria-label="Loan change type"
                  >
                    {(
                      [
                        ["all", "All", filteredChanges.length],
                        ["opened", "Opened", opened.length],
                        ["closed", "Closed", closed.length],
                        ["changed", "Changed", changed.length],
                      ] as const
                    ).map(([id, label, count]) => (
                      <button
                        key={id}
                        type="button"
                        role="tab"
                        aria-selected={tab === id}
                        className={segmentClass(tab === id)}
                        onClick={() => setTab(id)}
                      >
                        {label}
                        <span className="ml-1 tabular-nums text-muted-foreground">{count}</span>
                      </button>
                    ))}
                  </div>
                  <div className="relative w-full sm:max-w-xs">
                    <Search className="pointer-events-none absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2 text-muted-foreground" />
                    <Input
                      value={search}
                      onChange={(e) => setSearch(e.target.value)}
                      placeholder="Search bank, customer…"
                      className="h-8 bg-background pl-8 text-xs"
                      aria-label="Search loan changes"
                    />
                  </div>
                </div>

                <p className="text-muted-foreground text-xs leading-relaxed">
                  Net loan-line changes from the first to last snapshot in this chart range — same
                  window as Analytics period changes.
                </p>
              </section>

              {startLoading ? (
                <div className="flex items-center gap-2 py-10 text-muted-foreground text-sm">
                  <Loader2 className="size-4 animate-spin" />
                  Loading period-start loans…
                </div>
              ) : null}

              {startError ? <p className="text-destructive text-sm">{startError}</p> : null}

              {!startLoading && !startError && filteredChanges.length === 0 ? (
                <p className="py-10 text-center text-muted-foreground text-sm">
                  No loan opens, closes, or amount changes between these snapshots.
                </p>
              ) : null}

              {!startLoading && !startError && filteredChanges.length > 0 ? (
                <StickyTableScroll className="max-h-[max(20rem,calc(100dvh-22rem))] rounded-2xl border border-border/60 bg-card shadow-sm">
                  <table className="w-full min-w-[720px] border-collapse text-sm">
                    <thead>
                      <tr>
                        <SortableTh
                          label="Type"
                          direction={changeDir("kind")}
                          onSort={() => toggleChange("kind")}
                        />
                        <SortableTh
                          label="Bank"
                          direction={changeDir("bank")}
                          onSort={() => toggleChange("bank")}
                        />
                        {showCustomer ? (
                          <SortableTh
                            label="Customer"
                            direction={changeDir("customer")}
                            onSort={() => toggleChange("customer")}
                          />
                        ) : null}
                        <SortableTh
                          label={`Loan Δ (${reportingCurrency})`}
                          align="right"
                          direction={changeDir("amountDelta")}
                          onSort={() => toggleChange("amountDelta")}
                        />
                      </tr>
                    </thead>
                    <tbody>
                      {sortedChanges.map((row, index) => (
                        <tr
                          key={`${row.kind}-${row.bank}-${row.customer}-${index}`}
                          className={cn(
                            "border-border/60 border-t",
                            index % 2 === 1 && "bg-muted/20",
                          )}
                        >
                          <td className="px-3 py-2 text-muted-foreground whitespace-nowrap">
                            {row.kind}
                          </td>
                          <td className="max-w-[14rem] truncate px-3 py-2 font-medium" title={row.bank}>
                            {row.bank || "—"}
                          </td>
                          {showCustomer ? (
                            <td className="max-w-[12rem] truncate px-3 py-2" title={row.customer}>
                              {row.customer || "—"}
                            </td>
                          ) : null}
                          <td className="px-3 py-2 text-right whitespace-nowrap">
                            <div
                              className={cn(
                                "font-medium tabular-nums",
                                row.amountDelta > 0
                                  ? "text-emerald-600 dark:text-emerald-400"
                                  : row.amountDelta < 0
                                    ? "text-red-600 dark:text-red-400"
                                    : "text-foreground",
                              )}
                            >
                              {formatSignedAmount(
                                row.amountDelta,
                                reportingCurrency,
                                figuresMasked,
                              )}
                            </div>
                            <div className="text-[10px] tabular-nums text-muted-foreground">
                              {formatAmountPath(
                                row.amountBefore,
                                row.amountAfter,
                                reportingCurrency,
                                figuresMasked,
                              )}
                            </div>
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </StickyTableScroll>
              ) : null}
            </>
          ) : (
            <>
              <section className="grid gap-2 rounded-2xl bg-muted/40 p-3 sm:grid-cols-3">
                <InfoChip label="Loan Currency" value={currency || "—"} />
                <InfoChip label="As of" value={asOf || "—"} />
                <InfoChip label="Total Loan" value={loan ? money(loan.formatted) : "—"} />
              </section>

              {staticDetails.length === 0 ? (
                <p className="rounded-xl border border-dashed border-border/60 px-3 py-6 text-center text-sm text-muted-foreground">
                  No loan lines.
                </p>
              ) : (
                <StickyTableScroll className="max-h-[max(16rem,calc(100dvh-20rem))] border-0 bg-muted/20 shadow-none">
                  <table className="w-full border-collapse text-sm">
                    <thead>
                      <tr>
                        <SortableTh
                          label="Bank Name"
                          direction={directionFor("bank")}
                          onSort={() => toggle("bank")}
                        />
                        {showCustomer ? (
                          <SortableTh
                            label="Customer"
                            direction={directionFor("customer")}
                            onSort={() => toggle("customer")}
                          />
                        ) : null}
                        <SortableTh
                          label={`Loan (${reportingCurrency})`}
                          align="right"
                          direction={directionFor("amount")}
                          onSort={() => toggle("amount")}
                        />
                      </tr>
                    </thead>
                    <tbody>
                      {staticDetails.map((row, index) => (
                        <tr
                          key={`${row.bank}-${row.customer}-${index}`}
                          className={cn(
                            "border-t border-border/60",
                            index % 2 === 1 && "bg-muted/20",
                          )}
                        >
                          <td className="px-3 py-2">{row.bank}</td>
                          {showCustomer ? (
                            <td className="px-3 py-2">{row.customer || "—"}</td>
                          ) : null}
                          <td className="px-3 py-2 text-right tabular-nums text-red-600 dark:text-red-400">
                            {money(row.formatted)}
                          </td>
                        </tr>
                      ))}
                      <tr className="border-t border-border bg-muted/50 font-semibold">
                        <td className="px-3 py-2.5 text-right" colSpan={showCustomer ? 2 : 1}>
                          Total
                        </td>
                        <td className="px-3 py-2.5 text-right tabular-nums text-red-600 dark:text-red-400">
                          {loan ? money(loan.formatted) : "—"}
                        </td>
                      </tr>
                    </tbody>
                  </table>
                </StickyTableScroll>
              )}
            </>
          )}
        </div>
      </SheetContent>
    </Sheet>
  );
}
