import { useCallback, useEffect, useMemo, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { Files, GitBranch, Layers, Receipt } from "lucide-react";
import { Dialog, DialogContent } from "@/components/ui/dialog";
import { EmptyState } from "@/components/ui/empty-state";
import { ErrorState } from "@/components/ui/error-state";
import { Skeleton } from "@/components/ui/skeleton";
import { BatchesList, BatchesListSkeleton } from "@/components/BatchesList";
import {
  BatchDetailContent,
  BatchDetailError,
  BatchDetailSkeleton,
  batchErrorKind,
} from "@/components/BatchDetail";
import { useBatches } from "@/hooks/useBatches";
import { useDrawerKeyboard } from "@/hooks/useDrawerKeyboard";
import { api, ApiError, type BatchSummary } from "@/lib/api";
import { cn } from "@/lib/utils";
import type { ParseResult837, ParseResult835 } from "@/types";

function readBatchId(): string | null {
  const params = new URLSearchParams(window.location.search);
  const value = params.get("batch");
  return value === "" ? null : value;
}

function buildBatchUrl(batchId: string | null): string {
  const url = new URL(window.location.href);
  if (batchId === null) {
    url.searchParams.delete("batch");
  } else {
    url.searchParams.set("batch", batchId);
  }
  return url.pathname + url.search + url.hash;
}

function useBatchDrawerUrlState(): {
  batchId: string | null;
  open: (id: string) => void;
  close: () => void;
  setBatchId: (id: string) => void;
} {
  const [batchId, setBatchIdState] = useState<string | null>(() => readBatchId());

  const open = useCallback((id: string) => {
    window.history.pushState(null, "", buildBatchUrl(id));
    setBatchIdState(id);
  }, []);

  const setBatchId = useCallback((id: string) => {
    window.history.replaceState(null, "", buildBatchUrl(id));
    setBatchIdState(id);
  }, []);

  const close = useCallback(() => {
    window.history.pushState(null, "", buildBatchUrl(null));
    setBatchIdState(null);
  }, []);

  useEffect(() => {
    const onPopState = () => setBatchIdState(readBatchId());
    window.addEventListener("popstate", onPopState);
    return () => window.removeEventListener("popstate", onPopState);
  }, []);

  return { batchId, open, close, setBatchId };
}

function useBatchDetail(id: string | null): {
  data: (ParseResult837 | ParseResult835) | null;
  isLoading: boolean;
  isError: boolean;
  error: Error | null;
  refetch: () => void;
} {
  const q = useQuery<ParseResult837 | ParseResult835>({
    queryKey: ["batch-detail", id],
    queryFn: async () => {
      try {
        return await api.getBatch(id as string);
      } catch (err) {
        if (
          err instanceof Error &&
          err.message.startsWith("404")
        ) {
          throw new ApiError(404, err.message);
        }
        throw err;
      }
    },
    enabled: id !== null,
    staleTime: 30 * 1000,
    retry: (failureCount, error) => {
      if (error instanceof ApiError && error.status === 404) return false;
      return failureCount < 3;
    },
  });

  if (id === null) {
    return {
      data: null,
      isLoading: false,
      isError: false,
      error: null,
      refetch: () => {},
    };
  }

  return {
    data: q.data ?? null,
    isLoading: q.isLoading,
    isError: q.isError,
    error: q.error,
    refetch: () => {
      void q.refetch();
    },
  };
}

const HELP_NOOP = () => {};

/**
 * Batches page — hybrid Magazine Spread treatment.
 *
 * Dark editorial hero → torn-page fold → cream paper plane with the
 * batch register (KPI strip + tabular list). Click a row to open the
 * detail drawer (rendered above the page, dimmed via the body
 * opacity).
 */
export function Batches() {
  const { data, isLoading, isError, error, refetch } = useBatches(100);
  const items: BatchSummary[] = data ?? [];

  const { batchId, open, close, setBatchId } = useBatchDrawerUrlState();

  const { data: detail, isLoading: detailLoading, error: detailError, refetch: refetchDetail } =
    useBatchDetail(batchId);

  const { onNext, onPrev } = useMemo(() => {
    if (batchId === null || items.length === 0) {
      return { onNext: () => {}, onPrev: () => {} };
    }
    const idx = items.findIndex((b) => b.id === batchId);
    if (idx === -1) return { onNext: () => {}, onPrev: () => {} };
    return {
      onNext: () => {
        const nextId = items[(idx + 1) % items.length].id;
        setBatchId(nextId);
      },
      onPrev: () => {
        const prevId = items[(idx - 1 + items.length) % items.length].id;
        setBatchId(prevId);
      },
    };
  }, [batchId, items, setBatchId]);

  useDrawerKeyboard({
    enabled: batchId !== null,
    onNext,
    onPrev,
    onClose: close,
    onToggleHelp: HELP_NOOP,
  });

  const dimBackground = batchId !== null;
  const errKind = batchErrorKind(detailError);

  // -----------------------------------------------------------------
  // Aggregate metrics for the § 01 KPI strip
  // -----------------------------------------------------------------
  const totals = items.reduce(
    (acc, b) => ({
      count: acc.count + 1,
      p837: acc.p837 + (b.kind === "837p" ? 1 : 0),
      p835: acc.p835 + (b.kind === "835" ? 1 : 0),
      claims: acc.claims + b.claimCount,
    }),
    { count: 0, p837: 0, p835: 0, claims: 0 },
  );

  // -----------------------------------------------------------------
  // Stagger choreography (matches Acks / Reconciliation / Upload)
  // -----------------------------------------------------------------
  const heroDelay = 0;
  const foldDelay = 220;
  const titleDelay = 320;
  const kpiDelay = 460;
  const tableDelay = 600;

  return (
    <>
      <Dialog
        open={batchId !== null}
        onOpenChange={(open) => {
          if (!open) close();
        }}
      >
        <DialogContent
          className="fixed right-0 top-0 h-full w-full max-w-2xl translate-x-0 translate-y-0 rounded-none border-l border-border bg-card p-0"
          data-testid="batch-detail-drawer"
          aria-describedby={undefined}
        >
          {batchId === null ? null : detailLoading ? (
            <BatchDetailSkeleton />
          ) : errKind ? (
            <BatchDetailError
              kind={errKind}
              onRetry={() => {
                void refetchDetail();
              }}
              onClose={close}
            />
          ) : detail ? (
            <BatchDetailContent data={detail} onClose={close} />
          ) : null}
        </DialogContent>
      </Dialog>

      <div
        data-testid="batches-page-body"
        className={cn(
          "space-y-0 animate-fade-in transition-opacity",
          dimBackground && "pointer-events-none opacity-60",
        )}
      >
        {/* =================================================================
            HERO — DARK EDITORIAL HEADER
            ================================================================= */}
        <section
          className="relative pt-6 pb-8 lg:pt-9 lg:pb-10"
          style={{ animationDelay: `${heroDelay}ms` }}
        >
          {/* Ghost "PARSED" watermark — a print-shop stamp behind the title. */}
          <div
            aria-hidden="true"
            className="pointer-events-none select-none absolute inset-x-0 top-[58%] -translate-y-1/2 whitespace-nowrap display text-center"
            style={{
              fontSize: "clamp(160px, 20vw, 300px)",
              letterSpacing: "-0.05em",
              opacity: 0.05,
              lineHeight: 1,
              color: "hsl(var(--surface-ink))",
            }}
          >
            PARSED
          </div>

          <div className="relative z-10 grid grid-cols-1 lg:grid-cols-[1fr,auto] gap-8 items-end mb-7">
            <div className="min-w-0 max-w-3xl">
              <div className="flex items-center gap-3 mb-5">
                <div className="h-px w-14 bg-foreground/25" />
                <span className="mono text-[12px] uppercase tracking-[0.22em] text-muted-foreground">
                  Batches · Register
                </span>
                <span
                  className="mono text-[12px] uppercase tracking-[0.22em] text-muted-foreground/60 hidden sm:inline"
                  aria-hidden
                >
                  · {totals.count} on file
                </span>
              </div>
              <h1 className="display text-[48px] sm:text-[64px] lg:text-[80px] leading-[0.92] text-foreground tracking-[-0.04em]">
                Parsed{" "}
                <span className="italic text-muted-foreground/85">batches.</span>
              </h1>
            </div>
            <div className="flex flex-col items-start lg:items-end gap-3">
              <div className="inline-flex items-center gap-2 rounded-full border border-border/60 bg-card/60 px-3.5 py-2 text-[11.5px] mono uppercase tracking-[0.14em] text-muted-foreground backdrop-blur">
                <Files
                  className="h-3.5 w-3.5"
                  strokeWidth={1.75}
                  style={{ color: "hsl(var(--accent))" }}
                />
                837P · 835 · envelope & summary
              </div>
              <kbd
                className="mono text-[10.5px] uppercase tracking-[0.18em] text-muted-foreground/70"
              >
                Tap a row to open the drawer
              </kbd>
            </div>
          </div>

          <div className="relative z-10 max-w-2xl">
            <p className="text-[14px] text-muted-foreground leading-relaxed">
              Every 837P and 835 file the backend has ingested. Click a row
              for envelope, summary, and a peek at the contained claims.
            </p>
          </div>
        </section>

        {/* =================================================================
            FOLD — TORN PAGE
            ================================================================= */}
        <div
          aria-hidden
          className="relative h-14"
          style={{ animationDelay: `${foldDelay}ms` }}
        >
          <div
            className="absolute inset-x-0 top-0 h-1/2"
            style={{
              background:
                "linear-gradient(to bottom, hsl(0 0% 0% / 0.55), transparent)",
            }}
          />
          <div
            className="absolute inset-x-0 bottom-0 h-1/2"
            style={{
              background:
                "linear-gradient(to top, hsl(30 14% 14% / 0.18), transparent)",
            }}
          />
          <div
            className="absolute inset-x-0 top-1/2 -translate-y-1/2 h-px"
            style={{
              background:
                "linear-gradient(to right, transparent, hsl(30 14% 14% / 0.5) 12%, hsl(30 14% 14% / 0.7) 50%, hsl(30 14% 14% / 0.5) 88%, transparent)",
            }}
          />
          <div
            className="absolute inset-x-0 top-1/2 -translate-y-1/2 flex justify-between px-2"
            style={{ pointerEvents: "none" }}
          >
            {Array.from({ length: 48 }, (_, i) => (
              <span
                key={i}
                className="block h-[3px] w-[3px] rounded-full"
                style={{ backgroundColor: "hsl(30 14% 14% / 0.22)" }}
              />
            ))}
          </div>
          <div className="relative z-10 mx-auto h-full flex items-center justify-center gap-3 bg-background px-4 w-fit">
            <span
              className="display italic"
              style={{ color: "hsl(var(--muted-foreground))", fontSize: 15 }}
            >
              ↘
            </span>
            <span
              className="mono uppercase tracking-[0.24em]"
              style={{
                color: "hsl(var(--muted-foreground))",
                fontSize: 11,
                fontWeight: 500,
              }}
            >
              The register
            </span>
            <span
              className="display italic"
              style={{ color: "hsl(var(--muted-foreground))", fontSize: 15 }}
            >
              ↙
            </span>
          </div>
        </div>

        {/* =================================================================
            PAPER PLANE
            ================================================================= */}
        <div
          className="relative max-w-[1280px] mx-auto"
          style={{
            animationDelay: `${titleDelay}ms`,
            backgroundColor: "hsl(var(--surface))",
            boxShadow:
              "inset 0 1px 0 0 hsl(0 0% 100% / 0.5), 0 1px 0 0 hsl(30 14% 22% / 0.06), 0 30px 80px -24px hsl(0 0% 0% / 0.45)",
          }}
        >
          {/* Paper grain */}
          <div
            aria-hidden
            className="pointer-events-none absolute inset-0 opacity-[0.04]"
            style={{
              backgroundImage:
                "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.1  0 0 0 0 0.08  0 0 0 0 0.05  0 0 0 0.9 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>\")",
              backgroundSize: "160px 160px",
              mixBlendMode: "multiply",
            }}
          />

          {/* Title block */}
          <div
            className="relative px-8 lg:px-14 pt-12 pb-9 border-b animate-fade-in-up"
            style={{
              animationDelay: `${titleDelay}ms`,
              borderColor: "hsl(30 14% 14% / 0.12)",
            }}
          >
            <div
              aria-hidden
              className="absolute left-7 lg:left-12 top-0 bottom-0 w-px"
              style={{ backgroundColor: "hsl(30 14% 14% / 0.14)" }}
            />
            <div className="flex items-end justify-between gap-8 flex-wrap">
              <div>
                <div
                  className="mono text-[12px] uppercase tracking-[0.24em] mb-4 font-medium"
                  style={{ color: "hsl(var(--surface-ink-3))" }}
                >
                  Register · Parsed batches
                </div>
                <h2
                  className="display leading-[0.92] tracking-[-0.04em]"
                  style={{
                    color: "hsl(var(--surface-ink))",
                    fontSize: "clamp(48px, 7vw, 96px)",
                    fontWeight: 400,
                  }}
                >
                  The register.
                </h2>
                <div
                  className="mt-4 display italic"
                  style={{
                    color: "hsl(var(--surface-ink-2))",
                    fontSize: "clamp(15px, 1.3vw, 18px)",
                    lineHeight: 1.4,
                    maxWidth: "32ch",
                  }}
                >
                  One row per ingested file — the kind, the input filename,
                  how many claims it carried, and the day it was parsed.
                </div>
              </div>
              <div className="text-right shrink-0">
                <div
                  className="mono text-[11px] uppercase tracking-[0.24em] mb-1.5 font-medium"
                  style={{ color: "hsl(var(--surface-ink-3))" }}
                >
                  On file
                </div>
                <div
                  className="display tabular-nums"
                  style={{
                    color: "hsl(var(--surface-ink))",
                    fontSize: 26,
                    lineHeight: 1.1,
                  }}
                >
                  {totals.count}
                </div>
                <div
                  className="mono text-[11px] mt-1"
                  style={{ color: "hsl(var(--surface-ink-3))" }}
                >
                  batch{totals.count === 1 ? "" : "es"} · {totals.claims}{" "}
                  claim{totals.claims === 1 ? "" : "s"}
                </div>
              </div>
            </div>
          </div>

          {/* KPI strip — § 01 Vital signs */}
          <section
            aria-label="Batch register metrics"
            className="relative px-8 lg:px-14 py-7 animate-fade-in-up"
            style={{ animationDelay: `${kpiDelay}ms` }}
          >
            <div
              aria-hidden
              className="absolute left-7 lg:left-12 top-7 flex flex-col items-center gap-1"
            >
              <span
                className="mono text-[10px] uppercase tracking-[0.18em] font-semibold"
                style={{ color: "hsl(var(--surface-ink-3))" }}
              >
                § 01
              </span>
              <div
                className="w-px h-10"
                style={{ backgroundColor: "hsl(30 14% 14% / 0.18)" }}
              />
              <span
                className="display italic"
                style={{
                  color: "hsl(var(--surface-ink-2))",
                  fontSize: 11,
                  writingMode: "vertical-rl",
                  transform: "rotate(180deg)",
                  letterSpacing: "0.16em",
                }}
              >
                Vital signs
              </span>
            </div>
            <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
              <BatchesKpiTile
                label="On file"
                value={totals.count}
                icon={<Layers className="h-3 w-3" strokeWidth={1.75} />}
                tone="ink"
              />
              <BatchesKpiTile
                label="837P"
                value={totals.p837}
                icon={<GitBranch className="h-3 w-3" strokeWidth={1.75} />}
                tone="blue"
              />
              <BatchesKpiTile
                label="835"
                value={totals.p835}
                icon={<Receipt className="h-3 w-3" strokeWidth={1.75} />}
                tone="amber"
              />
              <BatchesKpiTile
                label="Claims"
                value={totals.claims}
                tone="success"
              />
            </div>
          </section>

          {/* Table — § 02 The register */}
          <section
            aria-label="Batch register"
            className="relative px-8 lg:px-14 pb-8 lg:pb-10 animate-fade-in-up"
            style={{ animationDelay: `${tableDelay}ms` }}
          >
            <div
              aria-hidden
              className="absolute left-7 lg:left-12 top-9 flex flex-col items-center gap-1"
            >
              <span
                className="mono text-[10px] uppercase tracking-[0.18em] font-semibold"
                style={{ color: "hsl(var(--surface-ink-3))" }}
              >
                § 02
              </span>
              <div
                className="w-px h-12"
                style={{ backgroundColor: "hsl(30 14% 14% / 0.18)" }}
              />
              <span
                className="display italic"
                style={{
                  color: "hsl(var(--surface-ink-2))",
                  fontSize: 11,
                  writingMode: "vertical-rl",
                  transform: "rotate(180deg)",
                  letterSpacing: "0.16em",
                }}
              >
                The register
              </span>
            </div>

            <div
              className="pt-6 border-t"
              style={{
                borderTopStyle: "double",
                borderTopWidth: 3,
                borderColor: "hsl(30 14% 14% / 0.12)",
              }}
            >
              <div className="flex items-end justify-between gap-6 flex-wrap mb-5">
                <div>
                  <div
                    className="mono text-[11.5px] uppercase tracking-[0.24em] font-semibold mb-2"
                    style={{ color: "hsl(var(--surface-ink-3))" }}
                  >
                    The register
                  </div>
                  <h3
                    className="display leading-[0.98] tracking-[-0.03em]"
                    style={{
                      color: "hsl(var(--surface-ink))",
                      fontSize: "clamp(24px, 2.6vw, 32px)",
                      fontWeight: 400,
                    }}
                  >
                    All <span className="italic">ingests</span>, newest first.
                  </h3>
                </div>
                <div
                  className="text-[12.5px] display italic"
                  style={{ color: "hsl(var(--surface-ink-2))", maxWidth: 380 }}
                >
                  Tap a row to open the envelope drawer. Use{" "}
                  <kbd
                    className="mono not-italic text-[10.5px] uppercase tracking-[0.14em] px-1 py-0.5 rounded-sm border"
                    style={{
                      borderColor: "hsl(30 14% 14% / 0.20)",
                      color: "hsl(var(--surface-ink))",
                    }}
                  >
                    ←
                  </kbd>{" "}
                  /{" "}
                  <kbd
                    className="mono not-italic text-[10.5px] uppercase tracking-[0.14em] px-1 py-0.5 rounded-sm border"
                    style={{
                      borderColor: "hsl(30 14% 14% / 0.20)",
                      color: "hsl(var(--surface-ink))",
                    }}
                  >
                    →
                  </kbd>{" "}
                  inside the drawer to step.
                </div>
              </div>

              {isError ? (
                <div
                  className="rounded-md border p-5"
                  style={{
                    borderColor: "hsl(30 14% 14% / 0.16)",
                    backgroundColor: "hsl(36 22% 96%)",
                  }}
                >
                  <ErrorState
                    message="Couldn't load batches from the backend."
                    detail={error instanceof Error ? error.message : String(error)}
                    onRetry={() => refetch()}
                  />
                </div>
              ) : isLoading ? (
                <div
                  className="rounded-md border p-4 space-y-2"
                  style={{
                    borderColor: "hsl(30 14% 14% / 0.10)",
                    backgroundColor: "hsl(36 22% 96%)",
                  }}
                >
                  <BatchesListSkeleton />
                </div>
              ) : items.length === 0 ? (
                <div
                  className="rounded-md border p-10 text-center"
                  style={{
                    borderColor: "hsl(30 14% 14% / 0.16)",
                    borderStyle: "dashed",
                    backgroundColor: "hsl(36 22% 96%)",
                  }}
                >
                  <EmptyState
                    eyebrow="Batches · awaiting first ingest"
                    message="Upload an 837P or 835 file on the Upload page to populate this list."
                  />
                </div>
              ) : (
                <div
                  className="rounded-md border overflow-hidden"
                  style={{
                    borderColor: "hsl(30 14% 14% / 0.10)",
                    backgroundColor: "hsl(36 22% 98%)",
                    boxShadow:
                      "inset 0 1px 0 0 hsl(0 0% 100% / 0.5)",
                  }}
                >
                  <BatchesList
                    items={items}
                    openId={batchId}
                    onOpen={open}
                    tone="paper"
                  />
                </div>
              )}
            </div>
          </section>

          {/* Footer */}
          <div
            className="relative px-8 lg:px-14 py-5 border-t flex items-center justify-between mono text-[10.5px] uppercase tracking-[0.18em]"
            style={{
              borderColor: "hsl(30 14% 14% / 0.12)",
              color: "hsl(var(--surface-ink-3))",
            }}
          >
            <span>End of register</span>
            <span>Cyclone · Batches</span>
            <span>
              {totals.count} {totals.count === 1 ? "row" : "rows"}
            </span>
          </div>
        </div>
      </div>
    </>
  );
}

// ---------------------------------------------------------------------------
// BatchesKpiTile — paper-toned metric for the batch register.
// Mirrors AckKpiTile / KpiTile in the other hybrid pages.
// ---------------------------------------------------------------------------
function BatchesKpiTile({
  label,
  value,
  tone,
  icon,
}: {
  label: string;
  value: number;
  tone: "blue" | "amber" | "ink" | "success";
  icon?: React.ReactNode;
}) {
  const accentMap = {
    blue: "hsl(212 100% 45%)",
    amber: "hsl(36 92% 50%)",
    ink: "hsl(var(--surface-ink))",
    success: "hsl(152 64% 38%)",
  } as const;
  const tintMap = {
    blue: "hsl(212 85% 92%)",
    amber: "hsl(36 82% 92%)",
    ink: "hsl(36 22% 90%)",
    success: "hsl(152 50% 88%)",
  } as const;
  const accent = accentMap[tone];
  const tint = tintMap[tone];
  return (
    <div
      className="relative rounded-xl p-5 overflow-hidden border"
      style={{
        backgroundColor: "hsl(var(--surface))",
        boxShadow:
          "inset 0 1px 0 0 hsl(0 0% 100% / 0.45), 0 1px 0 0 hsl(30 14% 22% / 0.06), inset 3px 0 0 0 hsl(0 0% 100% / 0.4)",
        borderColor: "hsl(30 14% 14% / 0.10)",
      }}
    >
      <div
        aria-hidden
        className="absolute left-0 top-5 bottom-5 w-[3px] rounded-r-sm"
        style={{ backgroundColor: accent, opacity: 0.85 }}
      />
      <div className="flex items-center justify-between mb-2.5">
        <div
          className="mono text-[10px] uppercase tracking-[0.18em] font-semibold"
          style={{ color: "hsl(var(--surface-ink-3))" }}
        >
          {label}
        </div>
        <div
          className="h-5 w-5 rounded-md flex items-center justify-center"
          style={{ backgroundColor: tint, color: accent }}
        >
          {icon ?? (
            <span
              className="block h-1.5 w-1.5 rounded-full"
              style={{ backgroundColor: accent }}
            />
          )}
        </div>
      </div>
      <div
        className="display tabular-nums tracking-[-0.04em]"
        style={{
          color: "hsl(var(--surface-ink))",
          fontSize: "clamp(28px, 3vw, 40px)",
          lineHeight: 1,
          fontWeight: 400,
        }}
      >
        {value}
      </div>
    </div>
  );
}
