import { useState } from "react";
import { GitMerge, CircleDashed, X } from "lucide-react";
import { toast } from "sonner";
import { useReconciliation } from "@/hooks/useReconciliation";
import { ApiError } from "@/lib/api";
import { Skeleton } from "@/components/ui/skeleton";
import { EmptyState } from "@/components/ui/empty-state";
import { ErrorState } from "@/components/ui/error-state";
import { PageHeader } from "@/components/PageHeader";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { RoleGate } from "@/auth/RoleGate";

/**
 * Two-column manual reconciliation surface. The operator picks one row from
 * the claims column, one from the remits column, then clicks "Match
 * selected" to POST /api/reconciliation/match. The hook's invalidation
 * cascade refreshes the unmatched bucket + claims + remits + activity feeds
 * on success.
 */
export function ReconciliationPage() {
  const { unmatched, match } = useReconciliation();
  const [selectedClaim, setSelectedClaim] = useState<string | null>(null);
  const [selectedRemit, setSelectedRemit] = useState<string | null>(null);

  if (unmatched.isLoading) {
    return (
      <div className="space-y-6 lg:space-y-8 animate-fade-in">
        <PageHeader
          eyebrow="Reconciliation"
          title={<>Manual <span className="display italic text-muted-foreground">pairing</span></>}
        />
        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <Skeleton variant="default" height={320} />
          <Skeleton variant="default" height={320} />
        </div>
      </div>
    );
  }

  if (unmatched.isError) {
    const detail =
      unmatched.error instanceof Error
        ? unmatched.error.message
        : String(unmatched.error);
    return (
      <div className="space-y-6 lg:space-y-8 animate-fade-in">
        <PageHeader
          eyebrow="Reconciliation"
          title={<>Manual <span className="display italic text-muted-foreground">pairing</span></>}
        />
        <ErrorState
          message="Couldn't load unmatched claims and remittances."
          detail={detail}
          onRetry={() => unmatched.refetch()}
        />
      </div>
    );
  }

  const { claims, remittances } = unmatched.data ?? {
    claims: [],
    remittances: [],
  };
  const empty = claims.length === 0 && remittances.length === 0;

  if (empty) {
    return (
      <div className="space-y-6 lg:space-y-8 animate-fade-in">
        <PageHeader
          eyebrow="Reconciliation"
          title={<>Manual <span className="display italic text-muted-foreground">pairing</span></>}
        />
        <div className="surface rounded-xl">
          <EmptyState
            icon={<CircleDashed className="h-4 w-4" strokeWidth={1.5} />}
            eyebrow="Reconciliation · nothing pending"
            message="Every claim and remittance is paired."
          />
        </div>
      </div>
    );
  }

  const handleMatch = async () => {
    if (!selectedClaim || !selectedRemit) return;
    try {
      await match.mutateAsync({ claimId: selectedClaim, remitId: selectedRemit });
      toast.success(`Matched ${selectedClaim} ↔ ${selectedRemit}`);
      setSelectedClaim(null);
      setSelectedRemit(null);
    } catch (e) {
      const msg =
        e instanceof ApiError && e.status === 409
          ? "Already matched — view the existing match."
          : e instanceof Error
            ? e.message
            : String(e);
      toast.error(msg);
    }
  };

  const handleClear = () => {
    setSelectedClaim(null);
    setSelectedRemit(null);
  };

  return (
    <div className="space-y-6 lg:space-y-8 animate-fade-in">
      <PageHeader
        eyebrow="Reconciliation"
        title={<>Manual <span className="display italic text-muted-foreground">pairing</span></>}
        subtitle="Pick one claim and one remittance, then match them."
      />

      <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
        {/* Claims column */}
        <div className="surface-2 rounded-xl p-4 space-y-2">
          <h2 className="eyebrow flex items-center justify-between">
            Unmatched claims
            <span className="mono text-[10.5px] text-foreground/80">{claims.length}</span>
          </h2>
          <div className="space-y-2">
            {claims.map((c) => {
              const active = selectedClaim === c.id;
              return (
                <button
                  key={c.id}
                  type="button"
                  onClick={() => setSelectedClaim(c.id)}
                  aria-pressed={active}
                  className={cn(
                    "w-full text-left p-3 min-h-[44px] rounded-md border transition-colors text-left",
                    active
                      ? "border-accent bg-accent/10 ring-1 ring-inset ring-accent/30"
                      : "border-border/60 hover:border-border hover:bg-muted/30"
                  )}
                >
                  <div className="display mono text-[13px]">{c.id}</div>
                  <div className="text-[12px] text-muted-foreground">
                    {c.patientName}
                  </div>
                  <div className="mono text-[11px] text-muted-foreground mt-0.5">
                    {c.serviceDate ?? "—"} · ${c.billedAmount.toFixed(2)} · NPI{" "}
                    {c.providerNpi ?? "—"}
                  </div>
                </button>
              );
            })}
          </div>
        </div>

        {/* Remits column */}
        <div className="surface-2 rounded-xl p-4 space-y-2">
          <h2 className="eyebrow flex items-center justify-between">
            Unmatched remits
            <span className="mono text-[10.5px] text-foreground/80">{remittances.length}</span>
          </h2>
          <div className="space-y-2">
            {remittances.map((r) => {
              const active = selectedRemit === r.id;
              return (
                <button
                  key={r.id}
                  type="button"
                  onClick={() => setSelectedRemit(r.id)}
                  aria-pressed={active}
                  className={cn(
                    "w-full text-left p-3 min-h-[44px] rounded-md border transition-colors text-left",
                    active
                      ? "border-accent bg-accent/10 ring-1 ring-inset ring-accent/30"
                      : "border-border/60 hover:border-border hover:bg-muted/30"
                  )}
                >
                  <div className="mono text-[13px] flex items-center gap-2">
                    {r.payerClaimControlNumber}
                    {r.isReversal ? (
                      <span className="text-[10px] text-warning uppercase tracking-wider">
                        Reversal
                      </span>
                    ) : null}
                  </div>
                  <div className="mono text-[11px] text-muted-foreground mt-0.5">
                    Status {r.status} · ${r.paidAmount.toFixed(2)} paid · $
                    {r.adjustmentAmount.toFixed(2)} adj
                  </div>
                </button>
              );
            })}
          </div>
        </div>
      </div>

      <div className="flex items-center gap-2 flex-wrap">
        {/* Match selected is the only true write affordance on this
            page — it transitions a claim from "submitted" /
            "rejected" to "paid" / "partial" / "denied" / "received"
            via `record_manual_match`. Viewers can still pick rows
            and see the selection chrome, but the button itself is
            disabled + tooltip-explained for them. */}
        <RoleGate allow={["admin", "user"]}>
          <Button
            onClick={handleMatch}
            disabled={!selectedClaim || !selectedRemit || match.isPending}
            className="min-h-[44px] sm:min-h-0"
          >
            <GitMerge className="h-3.5 w-3.5 mr-1.5" />
            Match selected
          </Button>
        </RoleGate>
        <Button
          variant="outline"
          onClick={handleClear}
          disabled={(!selectedClaim && !selectedRemit) || match.isPending}
          className="min-h-[44px] sm:min-h-0"
        >
          <X className="h-3.5 w-3.5 mr-1.5" />
          Clear selection
        </Button>
        {selectedClaim || selectedRemit ? (
          <span className="text-[11.5px] text-muted-foreground sm:ml-2 basis-full sm:basis-auto mono">
            {selectedClaim ? `Claim ${selectedClaim}` : "No claim"}
            {" · "}
            {selectedRemit ? `Remit ${selectedRemit}` : "No remit"}
          </span>
        ) : null}
      </div>
    </div>
  );
}
