import { useCallback, useMemo, useState } from "react";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { RemitStatusBadge } from "@/components/StatusBadge";
import { Skeleton } from "@/components/ui/skeleton";
import { EmptyState } from "@/components/ui/empty-state";
import { ErrorState } from "@/components/ui/error-state";
import { FilterChips, type FilterChipOption } from "@/components/ui/filter-chips";
import { Pagination } from "@/components/ui/pagination";
import { KeyboardCheatsheet } from "@/components/KeyboardCheatsheet";
import { PageHeader } from "@/components/PageHeader";
import { TailStatusPill } from "@/components/TailStatusPill";
import { RemitDrawer } from "@/components/RemitDrawer";
import { useRemittances } from "@/hooks/useRemittances";
import { useRemitDrawerUrlState } from "@/hooks/useRemitDrawerUrlState";
import { useRowKeyboard } from "@/hooks/useRowKeyboard";
import { useTailStream } from "@/hooks/useTailStream";
import { useMergedTail } from "@/hooks/useMergedTail";
import { fmt } from "@/lib/format";
import { cn } from "@/lib/utils";
import type { Remittance, RemittanceStatus } from "@/types";

const PAGE_SIZE = 25;

const STATUS_OPTIONS: FilterChipOption[] = [
  { value: "received", label: "Received" },
  { value: "posted", label: "Posted" },
  { value: "reconciled", label: "Reconciled" },
];

export function Remittances() {
  const [page, setPage] = useState(1);
  const [status, setStatus] = useState<RemittanceStatus | null>(null);
  const [selectedIndex, setSelectedIndex] = useState<number | null>(null);
  const [helpOpen, setHelpOpen] = useState(false);

  // SP21 Phase 4 Task 4.3: row click → RemitDrawer. The drawer is
  // URL-driven (`?remit=ID`) so deep links restore the open remit
  // on reload — same pattern as the ClaimDrawer on /claims.
  // `remits` is the j/k navigation list (the current page of rows).
  // `setRemitId` (REPLACE history, not push) is what j/k uses so a
  // single keypress doesn't add a history entry.
  const { remitId, open, close, setRemitId } = useRemitDrawerUrlState();

  const { data, isLoading, isError, error, refetch, dataUpdatedAt } = useRemittances({
    sort: "receivedDate",
    order: "desc",
    limit: PAGE_SIZE,
    offset: (page - 1) * PAGE_SIZE,
  });

  const tailFilterFn = useMemo(
    () => (r: Remittance) => {
      if (status && r.status !== status) return false;
      return true;
    },
    [status],
  );

  const { status: tailStatus, lastEventAt: tailLastEventAt, forceReconnect } =
    useTailStream("remittances");
  const items = useMergedTail("remittances", data?.items ?? [], tailFilterFn);

  const total = items.reduce(
    (acc, r) => ({
      paid: acc.paid + r.paidAmount,
      adjustments: acc.adjustments + r.adjustmentAmount,
    }),
    { paid: 0, adjustments: 0 }
  );

  const moveNext = useCallback(() => {
    setSelectedIndex((i) => {
      if (items.length === 0) return null;
      if (i === null) return 0;
      return (i + 1) % items.length;
    });
  }, [items.length]);

  const movePrev = useCallback(() => {
    setSelectedIndex((i) => {
      if (items.length === 0) return null;
      if (i === null) return items.length - 1;
      return (i - 1 + items.length) % items.length;
    });
  }, [items.length]);

  useRowKeyboard({
    // Page-level j/k only fires when the drawer is closed — once
    // `?remit=` is set, the drawer's own `useDrawerKeyboard` listener
    // owns the j/k keys (with its own wrap-around semantics over
    // `remits`). Letting the page-level listener stay active here
    // would mean a single `j` keypress both advances the drawer's
    // remittance AND bumps the page-level selectedIndex — exactly
    // the "double navigation" surprise we want to avoid.
    enabled: !helpOpen && items.length > 0 && remitId === null,
    onNext: moveNext,
    onPrev: movePrev,
    onClose: () => setHelpOpen(false),
    onToggleHelp: () => setHelpOpen((v) => !v),
  });

  // j/k navigation through the remits list. The drawer's own keyboard
  // handler (useDrawerKeyboard, only attached while the drawer is
  // open) uses the same keys with its own wrap-around semantics, so
  // page-level nav only fires when the drawer is closed.
  const drawerRemits = useMemo(
    () => items.map((r) => ({ id: r.id })),
    [items],
  );

  return (
    <>
      <KeyboardCheatsheet
        open={helpOpen}
        onClose={() => setHelpOpen(false)}
      />
      <RemitDrawer
        remitId={remitId}
        remits={drawerRemits}
        onClose={close}
        onNavigate={setRemitId}
        onToggleHelp={() => setHelpOpen((v) => !v)}
      />
      <div className="space-y-6 lg:space-y-8 animate-fade-in">
        <PageHeader
          eyebrow="Remittances"
          title={<>835 <span className="display italic text-muted-foreground">remittances</span></>}
          subtitle="Electronic remittance advice from payers, matched to submitted claims."
          actions={
            <TailStatusPill
              status={tailStatus}
              lastEventAt={tailLastEventAt}
              onReconnect={forceReconnect}
            />
          }
        />

        {isError ? (
          <ErrorState
            message="Couldn't load remittances from the backend."
            detail={error instanceof Error ? error.message : String(error)}
            onRetry={() => refetch()}
          />
        ) : null}

        <div className="grid gap-3.5 grid-cols-2 lg:grid-cols-3">
          <div className="surface-2 rounded-xl p-5">
            <div className="eyebrow">Remits</div>
            <div className="display mono text-[28px] leading-none mt-3 text-foreground">
              {fmt.num(data?.total ?? 0)}
            </div>
          </div>
          <div className="surface-2 rounded-xl p-5">
            <div className="eyebrow">Total paid</div>
            <div className="display mono text-[28px] leading-none mt-3 text-[hsl(var(--success))]">
              {fmt.usd(total.paid)}
            </div>
          </div>
          <div className="surface-2 rounded-xl p-5">
            <div className="eyebrow">Adjustments</div>
            <div className="display mono text-[28px] leading-none mt-3 text-[hsl(var(--warning))]">
              {fmt.usd(total.adjustments)}
            </div>
          </div>
        </div>

        <div className="surface rounded-xl p-4">
          <FilterChips
            options={STATUS_OPTIONS}
            value={status}
            onChange={(v) => {
              setStatus((v as RemittanceStatus | null) ?? null);
              setPage(1);
            }}
            eyebrow="Status"
          />
        </div>

        <div className="surface rounded-xl overflow-hidden">
          {isLoading ? (
            <div className="p-4 space-y-2">
              {Array.from({ length: 5 }).map((_, i) => (
                <Skeleton key={i} variant="row" />
              ))}
            </div>
          ) : items.length === 0 ? (
            <EmptyState
              eyebrow="Remittances · awaiting first 835"
              message="Drop an 835 file on the Upload page to populate this list."
            />
          ) : (
            <>
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>Remit</TableHead>
                    <TableHead>Claim</TableHead>
                    <TableHead>Payer</TableHead>
                    <TableHead className="text-right">Paid</TableHead>
                    <TableHead className="text-right">Adjustment</TableHead>
                    <TableHead>Status</TableHead>
                    <TableHead>Received</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {items.map((r, idx) => {
                    const isSelected = selectedIndex === idx;
                    return (
                      <TableRow
                        key={`${r.id}-${dataUpdatedAt}`}
                        data-row-index={idx}
                        data-state={isSelected ? "selected" : undefined}
                        aria-selected={isSelected}
                        className={cn(
                          "animate-row-flash cursor-pointer drillable",
                          isSelected && [
                            "bg-accent/10 ring-1 ring-inset ring-accent/40 shadow-[inset_2px_0_0_0_hsl(var(--accent))]",
                          ],
                        )}
                        onClick={() => open(r.id)}
                      >
                        <TableCell className="display mono text-[12.5px]">{r.id}</TableCell>
                        <TableCell className="display mono text-[12.5px] text-muted-foreground">
                          {r.claimId}
                        </TableCell>
                        <TableCell>{r.payerName}</TableCell>
                        <TableCell className="text-right display mono">
                          {fmt.usdPrecise(r.paidAmount)}
                        </TableCell>
                        <TableCell className="text-right display mono text-muted-foreground">
                          {r.adjustmentAmount > 0 ? fmt.usdPrecise(r.adjustmentAmount) : "—"}
                        </TableCell>
                        <TableCell>
                          <RemitStatusBadge status={r.status} />
                        </TableCell>
                        <TableCell className="text-muted-foreground mono text-[12px]">
                          {fmt.dateShort(r.receivedDate)}
                        </TableCell>
                      </TableRow>
                    );
                  })}
                </TableBody>
              </Table>
              <div className="px-4 pb-4">
                <Pagination
                  page={page}
                  pageSize={PAGE_SIZE}
                  total={data?.total ?? 0}
                  onPageChange={setPage}
                />
              </div>
            </>
          )}
        </div>
      </div>
    </>
  );
}
