import { useState } from "react";
import { createFileRoute } from "@tanstack/react-router";
import { useQuery } from "@tanstack/react-query";
import { Search, Users, Plus } from "lucide-react";
import { z } from "zod";

import { api } from "@/lib/api";
import { queryKeys } from "@/lib/queryKeys";

import { Button } from "@/components/ui/Button";
import { EmptyState } from "@/components/ui/EmptyState";
import {
  ClientTable,
  type ClientWithStats,
} from "@/components/clients/ClientTable";
import { ClientCardList } from "@/components/clients/ClientCardList";
import { ClientCreateDialog } from "@/components/clients/ClientCreateDialog";

const searchSchema = z.object({
  q: z.string().optional(),
});

export const Route = createFileRoute("/_app/clients")({
  validateSearch: searchSchema,
  component: ClientsPage,
  loader: ({ context }) => {
    void context.queryClient.prefetchQuery({
      queryKey: queryKeys.clients.list({}),
      queryFn: () =>
        api.get<ClientWithStats[]>("/api/v1/clients?withStats=1"),
    });
  },
});

function ClientsPage() {
  // Search local state pour le debounce — on évite de re-fetch à chaque
  // keystroke. Le param URL synchronisé via Route.useSearch() viendra V2 quand
  // on aura besoin de partager le filtre.
  const [searchInput, setSearchInput] = useState("");
  const [createOpen, setCreateOpen] = useState(false);

  const { data: clients = [], isPending } = useQuery({
    queryKey: queryKeys.clients.list({ q: searchInput }),
    queryFn: () => {
      const params = new URLSearchParams({ withStats: "1" });
      if (searchInput.trim()) params.set("q", searchInput.trim());
      return api.get<ClientWithStats[]>(`/api/v1/clients?${params}`);
    },
    staleTime: 10_000,
  });

  const totalLate = clients.reduce(
    (sum, c) => sum + c.lateInvoiceCount,
    0,
  );

  return (
    <div className="flex flex-col gap-5">
      <div className="flex flex-col gap-3 lg:flex-row lg:items-end lg:justify-between">
        <div>
          <h1 className="font-display text-[26px] font-bold tracking-[-0.022em] text-ink">
            Clients{" "}
            <span className="font-sans font-normal text-[14px] text-ink-3 align-middle">
              · {clients.length} fiche{clients.length > 1 ? "s" : ""}
            </span>
          </h1>
          <p className="mt-1 text-[13.5px] text-ink-3">
            {totalLate > 0 ? (
              <>
                <strong className="text-rubis-deep tabular-nums">
                  {totalLate}
                </strong>{" "}
                facture{totalLate > 1 ? "s" : ""} en retard chez{" "}
                {clients.filter((c) => c.lateInvoiceCount > 0).length} client
                {clients.filter((c) => c.lateInvoiceCount > 0).length > 1 ? "s" : ""}.
              </>
            ) : (
              "Tout est calme côté clients."
            )}
          </p>
        </div>

        <Button
          variant="secondary"
          size="sm"
          onClick={() => setCreateOpen(true)}
        >
          <Plus size={14} aria-hidden="true" /> Nouveau client
        </Button>
      </div>

      {/* Recherche */}
      <div className="relative max-w-md">
        <Search
          size={14}
          aria-hidden="true"
          className="absolute left-3.5 top-1/2 -translate-y-1/2 text-ink-3 pointer-events-none"
        />
        <input
          type="text"
          value={searchInput}
          onChange={(e) => setSearchInput(e.target.value)}
          placeholder="Rechercher un client par nom ou email…"
          className="block w-full rounded-default border border-line bg-white pl-10 pr-3 py-2.5 font-sans text-[14px] text-ink placeholder:text-ink-3 transition-[border-color,box-shadow] duration-150 focus:outline-none focus:border-rubis focus:ring-4 focus:ring-rubis-glow"
        />
      </div>

      {isPending ? (
        <SkeletonRows />
      ) : clients.length === 0 ? (
        <EmptyState
          icon={<Users size={32} strokeWidth={1.5} aria-hidden="true" />}
          title={
            searchInput.length > 0 ? (
              <>
                Aucun client ne <em className="text-rubis">correspond</em>.
              </>
            ) : (
              <>
                Pas encore de <em className="text-rubis">clients</em>.
              </>
            )
          }
          description={
            searchInput.length > 0
              ? "Essayez une autre recherche."
              : "Vos clients apparaîtront ici dès qu'une facture sera importée ou saisie."
          }
        />
      ) : (
        <>
          <div className="hidden lg:block">
            <ClientTable clients={clients} />
          </div>
          <div className="lg:hidden">
            <ClientCardList clients={clients} />
          </div>
        </>
      )}

      <ClientCreateDialog open={createOpen} onOpenChange={setCreateOpen} />
    </div>
  );
}

function SkeletonRows() {
  return (
    <div className="rounded-card border border-line bg-white">
      {Array.from({ length: 5 }).map((_, idx) => (
        <div
          key={idx}
          className="flex items-center gap-4 px-5 py-4 border-t border-line first:border-t-0 animate-pulse"
        >
          <div className="h-3 flex-1 rounded bg-cream-2" />
          <div className="h-3 w-16 rounded bg-cream-2" />
          <div className="h-3 w-24 rounded bg-cream-2" />
          <div className="h-3 w-28 rounded bg-cream-2" />
        </div>
      ))}
    </div>
  );
}
