import { Fragment, useCallback, useMemo, useState } from "react";
import { ChevronDown, ChevronRight, Receipt } from "lucide-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 { useRemittances } from "@/hooks/useRemittances";
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 { CasAdjustment, Remittance, RemittanceStatus } from "@/types";

const PAGE_SIZE = 25;

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

/**
 * One persisted CAS row, rendered as a "code — label" pair plus the
 * dollar amount. Lives inside the expanded detail row of a remit so
 * the operator can see exactly why the payer adjusted the claim.
 */
function AdjustmentRow({ adj }: { adj: CasAdjustment }) {
  return (
    <div className="flex items-start justify-between gap-4 py-2 border-b border-border/30 last:border-0">
      <div className="min-w-0 flex-1">
        <div className="mono text-[10.5px] text-muted-foreground">
          {adj.group}-{adj.reason}
          {adj.quantity !== null ? (
            <span className="ml-2 text-muted-foreground/60">
              qty {adj.quantity}
            </span>
          ) : null}
        </div>
        <div className="text-[12.5px] text-foreground/90 truncate">{adj.label}</div>
      </div>
      <div className="display mono text-[12.5px] tabular-nums whitespace-nowrap text-muted-foreground">
        {fmt.usdPrecise(adj.amount)}
      </div>
    </div>
  );
}

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

  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 toggleExpand = (id: string) => {
    setExpanded((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  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({
    enabled: !helpOpen && items.length > 0,
    onNext: moveNext,
    onPrev: movePrev,
    onClose: () => setHelpOpen(false),
    onToggleHelp: () => setHelpOpen((v) => !v),
  });

  return (
    <>
      <KeyboardCheatsheet
        open={helpOpen}
        onClose={() => setHelpOpen(false)}
      />
      <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 className="w-8" aria-label="Expand" />
                    <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 isOpen = expanded.has(r.id);
                    const hasAdjustments =
                      !!r.adjustments && r.adjustments.length > 0;
                    const isSelected = selectedIndex === idx;
                    return (
                      <Fragment key={`${r.id}-${dataUpdatedAt}`}>
                        <TableRow
                          data-row-index={idx}
                          data-state={isSelected ? "selected" : undefined}
                          aria-selected={isSelected}
                          className={cn(
                            "animate-row-flash",
                            isSelected && [
                              "bg-accent/10 ring-1 ring-inset ring-accent/40 shadow-[inset_2px_0_0_0_hsl(var(--accent))]",
                            ],
                          )}
                          onClick={() =>
                            hasAdjustments ? toggleExpand(r.id) : undefined
                          }
                          aria-expanded={hasAdjustments ? isOpen : undefined}
                          style={{ cursor: hasAdjustments ? "pointer" : undefined }}
                        >
                          <TableCell className="text-muted-foreground">
                            {hasAdjustments ? (
                              isOpen ? (
                                <ChevronDown
                                  className="h-3.5 w-3.5"
                                  strokeWidth={1.75}
                                  aria-hidden
                                />
                              ) : (
                                <ChevronRight
                                  className="h-3.5 w-3.5"
                                  strokeWidth={1.75}
                                  aria-hidden
                                />
                              )
                            ) : null}
                          </TableCell>
                          <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>
                        {isOpen && hasAdjustments ? (
                          <TableRow
                            key={`${r.id}-${dataUpdatedAt}-detail`}
                            className="bg-muted/20 hover:bg-muted/20"
                          >
                            <TableCell />
                            <TableCell colSpan={7} className="py-3">
                              <div className="flex items-center gap-2 mb-2">
                                <Receipt
                                  className="h-3.5 w-3.5 text-muted-foreground"
                                  strokeWidth={1.5}
                                  aria-hidden
                                />
                                <div className="eyebrow">
                                  Adjustments ({r.adjustments!.length})
                                </div>
                              </div>
                              <div className="pl-5">
                                {r.adjustments!.map((adj, i) => (
                                  <AdjustmentRow
                                    key={`${adj.group}-${adj.reason}-${i}`}
                                    adj={adj}
                                  />
                                ))}
                              </div>
                            </TableCell>
                          </TableRow>
                        ) : null}
                      </Fragment>
                    );
                  })}
                </TableBody>
              </Table>
              <div className="px-4 pb-4">
                <Pagination
                  page={page}
                  pageSize={PAGE_SIZE}
                  total={data?.total ?? 0}
                  onPageChange={setPage}
                />
              </div>
            </>
          )}
        </div>
      </div>
    </>
  );
}
