import { useEffect, useMemo, useRef, useState } from "react";
import { ChevronLeft, ChevronRight, Download, X } from "lucide-react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent } from "@/components/ui/dialog";
import { Spinner } from "@/components/ui/spinner";

/**
 * BankStatementPDFViewer — WealthX DS (L4 Template)
 *
 * Full-viewport dialog for viewing a bank statement PDF.
 * Supports paging through multiple accounts using prev / next navigation.
 *
 * PDF rendering:
 *   - Embeds the blob via `URL.createObjectURL(pdfBlob) + "#toolbar=0"` in an
 *     `<iframe>` so the browser's native PDF plugin renders it without toolbar.
 *   - Object URL is revoked automatically when the blob changes.
 *
 * Typical usage in the Bank Statement tab:
 *   1. User clicks a document name in `BankStatementDocumentTable`.
 *   2. Consumer fetches the PDF blob for each linked account.
 *   3. `BankStatementPDFViewer` is mounted with `open={true}`.
 *   4. User pages through accounts with ‹ / ›; download icon triggers a direct
 *      browser download of the current blob.
 *
 * Layer: L4 Template
 */

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

export interface BankStatementViewerAccount {
  id: string;
  /** Account display name (e.g. "Everyday Savings"). */
  name?: string;
  /** Institution name fallback (e.g. "CommBank"). */
  institutionName?: string;
}

export interface BankStatementPDFViewerProps {
  open: boolean;
  onClose: () => void;
  /** Raw PDF blob for the currently viewed document. `null` shows an empty state. */
  pdfBlob: Blob | null;
  /** Filename used for the browser download, e.g. "CommBank_James_90days.pdf". */
  pdfFilename?: string;
  /** All accounts linked to this statement (for prev/next navigation). */
  accounts: BankStatementViewerAccount[];
  /** Zero-based index of the currently viewed account. */
  currentAccountIndex: number;
  /** Called when the user clicks ‹ / › to navigate between accounts. */
  onAccountChange: (index: number) => void;
  className?: string;
}

// ---------------------------------------------------------------------------
// BankStatementPDFViewer
// ---------------------------------------------------------------------------

export function BankStatementPDFViewer({
  open,
  onClose,
  pdfBlob,
  pdfFilename,
  accounts,
  currentAccountIndex,
  onAccountChange,
  className,
}: BankStatementPDFViewerProps) {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const previousUrlRef = useRef<string | null>(null);

  // Create an object URL from the blob (memoised; revoked when blob changes)
  const pdfUrl = useMemo(() => {
    if (!pdfBlob) return null;
    return `${URL.createObjectURL(pdfBlob)}#toolbar=0`;
  }, [pdfBlob]);

  // Revoke the previous URL when the blob changes to avoid memory leaks
  useEffect(() => {
    return () => {
      if (pdfUrl) {
        // Strip the #toolbar=0 fragment before revoking
        URL.revokeObjectURL(pdfUrl.split("#")[0]);
      }
    };
  }, [pdfUrl]);

  // Reset loading state when the URL (blob or account) changes
  useEffect(() => {
    if (!pdfUrl) {
      setLoading(false);
      return;
    }

    if (previousUrlRef.current !== pdfUrl) {
      previousUrlRef.current = pdfUrl;
      setLoading(true);
      setError(null);
    }

    // Fallback: hide spinner after 2 s even if onLoad never fires (e.g. Firefox)
    const timer = setTimeout(() => setLoading(false), 2000);
    return () => clearTimeout(timer);
  }, [pdfUrl, currentAccountIndex]);

  // ── Navigation ────────────────────────────────────────────────────────────

  const canGoPrev = currentAccountIndex > 0;
  const canGoNext = currentAccountIndex < accounts.length - 1;

  const currentAccount = accounts[currentAccountIndex];
  const accountLabel =
    currentAccount?.name ?? currentAccount?.institutionName ?? "Account";

  // ── Download ──────────────────────────────────────────────────────────────

  const handleDownload = () => {
    if (!pdfBlob) return;
    const filename = pdfFilename ?? "bank-statement.pdf";
    const url = URL.createObjectURL(pdfBlob);
    const anchor = document.createElement("a");
    anchor.href = url;
    anchor.download = filename;
    document.body.appendChild(anchor);
    anchor.click();
    document.body.removeChild(anchor);
    URL.revokeObjectURL(url);
  };

  // ── Render ────────────────────────────────────────────────────────────────

  return (
    <Dialog open={open} onOpenChange={(o) => !o && onClose()}>
      <DialogContent
        showCloseButton={false}
        className={cn(
          "flex h-[95vh] max-h-[95vh] w-[95vw] max-w-[95vw] flex-col gap-0 p-0",
          className,
        )}
        data-slot="bank-statement-pdf-viewer"
      >
        {/* Navigation bar */}
        <div className="flex min-w-0 shrink-0 items-center justify-between border-b border-border px-3 py-2">
          <div className="flex min-w-0 items-center gap-2">
            <Button
              variant="ghost"
              size="icon-sm"
              aria-label="Previous account"
              onClick={() => onAccountChange(currentAccountIndex - 1)}
              disabled={!canGoPrev}
            >
              <ChevronLeft className="size-4" />
            </Button>

            <span className="shrink-0 text-body-medium tabular-nums">
              Account {currentAccountIndex + 1} of {accounts.length}
            </span>

            <Button
              variant="ghost"
              size="icon-sm"
              aria-label="Next account"
              onClick={() => onAccountChange(currentAccountIndex + 1)}
              disabled={!canGoNext}
            >
              <ChevronRight className="size-4" />
            </Button>

            <span className="ml-2 min-w-0 truncate text-body-medium text-muted-foreground">
              {accountLabel}
            </span>
          </div>

          <div className="flex items-center gap-1">
            <Button
              variant="ghost"
              size="icon-sm"
              aria-label="Download PDF"
              onClick={handleDownload}
              disabled={!pdfBlob}
            >
              <Download className="size-4" />
            </Button>
            <Button
              variant="ghost"
              size="icon-sm"
              aria-label="Close viewer"
              onClick={onClose}
            >
              <X className="size-4" />
            </Button>
          </div>
        </div>

        {/* PDF area */}
        <div className="relative flex flex-1 items-start justify-center overflow-auto bg-muted">
          {!pdfBlob ? (
            <div className="flex h-full w-full items-center justify-center">
              <p className="text-body-medium text-muted-foreground">
                No PDF document available
              </p>
            </div>
          ) : (
            <>
              {loading && (
                <div className="absolute left-1/2 top-1/2 z-10 flex -translate-x-1/2 -translate-y-1/2 flex-col items-center gap-2">
                  <Spinner />
                  <p className="text-body-medium text-muted-foreground">
                    Loading PDF…
                  </p>
                </div>
              )}

              {error && !loading && (
                <div className="absolute left-1/2 top-1/2 z-10 -translate-x-1/2 -translate-y-1/2">
                  <p className="text-body-medium text-destructive">{error}</p>
                </div>
              )}

              <iframe
                key={pdfUrl ?? "no-url"}
                src={pdfUrl ?? undefined}
                className="min-h-full w-full max-w-[1000px] border-none transition-opacity duration-300"
                style={{ opacity: loading ? 0 : 1 }}
                title="Bank Statement PDF"
                onLoad={() => setLoading(false)}
                onError={() => {
                  setLoading(false);
                  setError("Failed to load PDF");
                }}
              />
            </>
          )}
        </div>
      </DialogContent>
    </Dialog>
  );
}
