import { useMemo, useRef, useState } from "react";
import { Search, X } from "lucide-react";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { ClaimStatusBadge } from "@/components/StatusBadge";
import { NewClaimDialog } from "@/components/NewClaimDialog";
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 { useClaims } from "@/hooks/useClaims";
import { useAppStore } from "@/store";
import { fmt } from "@/lib/format";
import type { ClaimStatus } from "@/types";
import { cn } from "@/lib/utils";

const ALL = "all" as const;
const PAGE_SIZE = 25;

const STATUS_OPTIONS: FilterChipOption[] = [
  { value: "all", label: "All" },
  { value: "submitted", label: "Submitted" },
  { value: "accepted", label: "Accepted" },
  { value: "denied", label: "Denied" },
  { value: "paid", label: "Paid" },
  { value: "pending", label: "Pending" },
];

export function Claims() {
  const [status, setStatus] = useState<ClaimStatus | typeof ALL>(ALL);
  const [npi, setNpi] = useState<string>(ALL);
  const [query, setQuery] = useState("");
  const [page, setPage] = useState(1);
  const searchRef = useRef<HTMLInputElement>(null);

  const providers = useAppStore((s) => s.providers);
  const providerMap = useMemo(
    () => Object.fromEntries(providers.map((p) => [p.npi, p])),
    [providers]
  );

  const params = {
    status: status === ALL ? undefined : status,
    provider_npi: npi === ALL ? undefined : npi,
    sort: "billedAmount",
    order: "desc" as const,
    limit: PAGE_SIZE,
    offset: (page - 1) * PAGE_SIZE,
  };

  const { data, isLoading, isError, error, refetch } = useClaims(params);
  const items = data?.items ?? [];

  const totals = useMemo(
    () => ({
      billed: items.reduce((s, c) => s + c.billedAmount, 0),
      received: items.reduce((s, c) => s + c.receivedAmount, 0),
    }),
    [items]
  );

  // Local search filter on the current page (cheap; no extra fetch).
  const visible = useMemo(() => {
    const q = query.trim().toLowerCase();
    if (!q) return items;
    return items.filter(
      (c) =>
        c.id.toLowerCase().includes(q) ||
        c.patientName.toLowerCase().includes(q) ||
        c.payerName.toLowerCase().includes(q) ||
        c.cptCode.toLowerCase().includes(q)
    );
  }, [items, query]);

  const filtered = status !== ALL || npi !== ALL;

  return (
    <div className="space-y-8 animate-fade-in">
      <header className="flex items-end justify-between gap-6 flex-wrap">
        <div>
          <div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
            <span className="inline-block h-px w-6 bg-border" />
            Claims
          </div>
          <h1 className="text-[22px] font-semibold tracking-tight">All claims</h1>
        </div>
        <NewClaimDialog />
      </header>

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

      <div className="surface rounded-xl p-4">
        <div className="flex flex-wrap items-center gap-3">
          <div className="relative flex-1 min-w-[240px]">
            <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
            <Input
              ref={searchRef}
              placeholder="Search by claim ID, patient, payer, CPT…"
              value={query}
              onChange={(e) => setQuery(e.target.value)}
              className="pl-9 pr-16"
            />
            {query ? (
              <button
                type="button"
                onClick={() => setQuery("")}
                className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground p-1.5 rounded-md"
                aria-label="Clear search"
              >
                <X className="h-3.5 w-3.5" />
              </button>
            ) : null}
          </div>

          <Select
            value={npi}
            onValueChange={(v) => {
              setNpi(v);
              setPage(1);
            }}
          >
            <SelectTrigger className="w-[240px]">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value={ALL}>All providers</SelectItem>
              {providers.map((p) => (
                <SelectItem key={p.npi} value={p.npi}>
                  {p.npi} — {p.name}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>

        <div className="mt-3">
          <FilterChips
            options={STATUS_OPTIONS}
            value={status === ALL ? null : status}
            onChange={(v) => {
              setStatus((v as ClaimStatus | null) ?? ALL);
              setPage(1);
            }}
            eyebrow="Status"
          />
        </div>

        <div className="flex items-center gap-6 mt-4 pt-4 border-t border-border/40 text-xs text-muted-foreground">
          <span>
            <span className="num text-foreground font-medium">
              {fmt.num(data?.total ?? 0)}
            </span>{" "}
            claims
          </span>
          <span>
            Billed{" "}
            <span className="num text-foreground font-medium">
              {fmt.usd(totals.billed)}
            </span>
          </span>
          <span>
            Received{" "}
            <span className="num text-foreground font-medium">
              {fmt.usd(totals.received)}
            </span>
          </span>
        </div>
      </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="Claims · inbox idle"
            message={
              filtered
                ? "No claims match the current filters."
                : "Drop an 837P file on the Upload page to populate this list."
            }
          />
        ) : (
          <>
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Claim</TableHead>
                  <TableHead>Patient</TableHead>
                  <TableHead>Provider</TableHead>
                  <TableHead>Payer</TableHead>
                  <TableHead className="text-right">Billed</TableHead>
                  <TableHead className="text-right">Received</TableHead>
                  <TableHead>Status</TableHead>
                  <TableHead>Submitted</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {visible.map((c) => {
                  const provider = providerMap[c.providerNpi];
                  return (
                    <TableRow
                      key={c.id}
                      className={cn(
                        "animate-row-flash",
                        // Suppress flash when filtering so only the new
                        // page's first paint flashes; subsequent renders
                        // use the existing fade-in from the page wrapper.
                      )}
                    >
                      <TableCell>
                        <div className="display num text-[13px]">{c.id}</div>
                        <div className="text-[11px] text-muted-foreground num">
                          CPT {c.cptCode}
                        </div>
                      </TableCell>
                      <TableCell className="font-medium">{c.patientName}</TableCell>
                      <TableCell>
                        <div className="text-sm">{provider?.name ?? "Unknown"}</div>
                        <div className="text-[11px] text-muted-foreground num">
                          {c.providerNpi}
                        </div>
                      </TableCell>
                      <TableCell className="text-muted-foreground">
                        {c.payerName}
                      </TableCell>
                      <TableCell className="text-right display num">
                        {fmt.usd(c.billedAmount)}
                      </TableCell>
                      <TableCell className="text-right display num text-muted-foreground">
                        {c.receivedAmount > 0 ? fmt.usd(c.receivedAmount) : "—"}
                      </TableCell>
                      <TableCell>
                        <ClaimStatusBadge status={c.status} />
                      </TableCell>
                      <TableCell className="text-muted-foreground text-[13px] num">
                        {fmt.dateShort(c.submissionDate)}
                      </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>
  );
}
