import { useEffect } from "react";
import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { ArrowLeft, Check, Send } from "lucide-react";
import { toast } from "sonner";
import { z } from "zod";

import type { Client, Invoice, Plan } from "@rubis/shared";
import { api } from "@/lib/api";
import { useCheckinStillPending } from "@/lib/checkin";
import { queryKeys } from "@/lib/queryKeys";
import { formatEuros, formatDate, formatDueDelta, isOverdue } from "@/lib/format";

import { Button } from "@/components/ui/Button";
import { Card } from "@/components/ui/Card";
import { Eyebrow } from "@/components/ui/Eyebrow";
import { StatusBadge } from "@/components/ui/StatusBadge";
import { Timeline, type TimelineEvent } from "@/components/ui/Timeline";
import { Textarea } from "@/components/ui/Textarea";
import { PdfPreview } from "@/components/factures/PdfPreview";

const checkinSearchSchema = z.object({
  checkin: z.enum(["paid", "pending", "expired", "invalid", "already_answered"]).optional(),
  invoice: z.string().optional(),
});

type InvoiceDetail = Invoice & {
  client: Client;
  plan: Plan | null;
  timeline: TimelineEvent[];
  /** Override du label statut (ex: "Relance J+3 envoyée"). */
  statusLabel?: string;
};

export const Route = createFileRoute("/_app/factures_/$id")({
  validateSearch: checkinSearchSchema,
  component: InvoiceDetailPage,
  loader: ({ context, params }) => {
    void context.queryClient.prefetchQuery({
      queryKey: queryKeys.invoices.detail(params.id),
      queryFn: () => api.get<InvoiceDetail>(`/api/v1/invoices/${params.id}`),
    });
  },
});

function InvoiceDetailPage() {
  const { id } = Route.useParams();
  const search = Route.useSearch();
  const queryClient = useQueryClient();
  const navigate = useNavigate();

  const {
    data: invoice,
    isPending,
    isError,
  } = useQuery({
    queryKey: queryKeys.invoices.detail(id),
    queryFn: () => api.get<InvoiceDetail>(`/api/v1/invoices/${id}`),
  });

  const markPaidMutation = useMutation({
    mutationFn: () => api.post<InvoiceDetail>(`/api/v1/invoices/${id}/mark-paid`),
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: queryKeys.invoices.all() });
      void queryClient.invalidateQueries({ queryKey: queryKeys.dashboard.kpis() });
      toast.success("Encaissée. + 1 rubis bien mérité.");
      void navigate({ to: "/factures" });
    },
    onError: () => {
      toast.error("On n'a pas pu marquer la facture. Réessayez.");
    },
  });

  // "Relancer maintenant" : court-circuite le check-in, programme les
  // relances + bascule l'invoice en `in_relance` immédiatement. Réutilise
  // l'endpoint inappRespondPending qui fait exactement ça.
  const launchRelanceMutation = useCheckinStillPending();

  useEffect(() => {
    const checkin = search.checkin;
    if (!checkin) return;

    const labels: Record<typeof checkin, string> = {
      paid: "Facture marquée encaissée.",
      pending: "Relance activée pour cette facture.",
      expired: "Ce lien de confirmation a expiré.",
      invalid: "Ce lien de confirmation est invalide.",
      already_answered: "Cette confirmation avait déjà été traitée.",
    };

    const isErrorToast = checkin === "expired" || checkin === "invalid";
    if (isErrorToast) toast.error(labels[checkin]);
    else toast.success(labels[checkin]);

    void queryClient.invalidateQueries({ queryKey: queryKeys.invoices.detail(id) });
    void queryClient.invalidateQueries({ queryKey: queryKeys.invoices.all() });
    void queryClient.invalidateQueries({ queryKey: queryKeys.dashboard.kpis() });
    void navigate({
      to: "/factures/$id",
      params: { id },
      search: {},
      replace: true,
    });
  }, [id, navigate, queryClient, search.checkin]);

  if (isError) {
    return (
      <div className="text-center py-12">
        <p className="font-display text-[20px] font-semibold text-ink">Facture introuvable.</p>
        <Link
          to="/factures"
          className="mt-3 inline-block text-[13px] text-rubis underline-offset-4 hover:underline"
        >
          ← Retour aux factures
        </Link>
      </div>
    );
  }

  if (isPending || !invoice) {
    return <InvoiceDetailSkeleton />;
  }

  const overdue = isOverdue(invoice.dueDate);
  const isPaid = invoice.status === "paid";

  return (
    <div className="flex flex-col gap-6">
      <Link
        to="/factures"
        className="inline-flex items-center gap-1.5 self-start text-[12.5px] text-ink-3 hover:text-rubis"
      >
        <ArrowLeft size={13} aria-hidden="true" /> Factures
      </Link>

      <header className="flex flex-col gap-5 lg:flex-row lg:items-end lg:justify-between">
        <div className="min-w-0">
          <Eyebrow>{invoice.client.name}</Eyebrow>
          <h1 className="mt-2 font-display text-[28px] font-bold tracking-[-0.022em] text-ink lg:text-[32px]">
            Facture {invoice.numero}
          </h1>
          <p className="mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-[14px] text-ink-2">
            <span className="font-display text-[18px] font-semibold text-ink tabular-nums">
              {formatEuros(invoice.amountTtcCents)}
            </span>
            <span className="text-ink-3">·</span>
            <span>
              échue le{" "}
              <span className={overdue ? "font-semibold text-ink" : ""}>
                {formatDate(invoice.dueDate)}
              </span>{" "}
              <span
                className={`tabular-nums ${
                  overdue ? "font-semibold text-rubis-deep" : "text-ink-3"
                }`}
              >
                ({formatDueDelta(invoice.dueDate)})
              </span>
            </span>
            <StatusBadge status={invoice.status} label={invoice.statusLabel} className="ml-1" />
          </p>
        </div>

        {!isPaid && invoice.status !== "litigation" && (
          <div className="flex flex-wrap gap-2">
            <Button
              variant="secondary"
              size="sm"
              loading={markPaidMutation.isPending}
              onClick={() => markPaidMutation.mutate()}
            >
              <Check size={14} aria-hidden="true" /> Marquer encaissée
            </Button>
            {/* "Relancer maintenant" : actif pour pending et awaiting_user_confirmation
                — court-circuite le check-in et déclenche immédiatement le plan.
                Désactivé pour `in_relance` car le plan tourne déjà. */}
            <Button
              size="sm"
              loading={launchRelanceMutation.isPending}
              disabled={
                invoice.status !== "pending" &&
                invoice.status !== "awaiting_user_confirmation"
              }
              onClick={() =>
                launchRelanceMutation.mutate(invoice.id, {
                  onSuccess: () => {
                    toast.success(
                      `Relances activées pour ${invoice.numero}.`,
                    );
                  },
                  onError: () =>
                    toast.error(
                      "Impossible de programmer les relances. Réessayez.",
                    ),
                })
              }
            >
              <Send size={14} aria-hidden="true" /> Relancer maintenant
            </Button>
          </div>
        )}
      </header>

      <div className="grid grid-cols-1 gap-6 lg:grid-cols-[1.1fr_1fr]">
        {/* PDF source — colonne gauche, document tel qu'importé */}
        <PdfPreview
          filename={`${invoice.numero}.pdf`}
          invoiceId={invoice.id}
          pdfAvailable={!!invoice.pdfStorageKey}
        />

        {/* Colonne droite : timeline + client + notes empilés */}
        <div className="flex flex-col gap-4">
          <Card padding="md">
            <Eyebrow tone="ink">
              Timeline
              {invoice.plan && <span className="text-ink-3"> · plan {invoice.plan.name}</span>}
            </Eyebrow>
            {!isPaid && invoice.status !== "litigation" && invoice.plan && (
              <p className="mt-3 rounded-sharp bg-cream-2/60 px-3 py-2 text-[12px] text-ink-2 leading-snug">
                <strong className="text-ink">Aucune relance ne part sans votre validation.</strong>{" "}
                Avant chaque envoi, Rubis vous demande si la facture a été réglée — vous gardez la main.
              </p>
            )}
            <Timeline events={invoice.timeline} className="mt-5" />
          </Card>

          <Card padding="md">
            <Eyebrow tone="ink">Client</Eyebrow>
            <p className="mt-3 font-display text-[16px] font-semibold text-ink">
              {invoice.client.name}
            </p>
            {invoice.client.email && (
              <p className="mt-1 text-[13.5px] text-ink-2 truncate">{invoice.client.email}</p>
            )}
            {invoice.client.phone && (
              <p className="mt-0.5 text-[13.5px] text-ink-2">{invoice.client.phone}</p>
            )}
            {invoice.client.address && (
              <p className="mt-2 text-[12.5px] leading-relaxed text-ink-3">
                {invoice.client.address}
              </p>
            )}
          </Card>

          <Card padding="md">
            <Eyebrow tone="ink">Notes internes</Eyebrow>
            <Textarea
              defaultValue={invoice.notes ?? invoice.client.notes ?? ""}
              placeholder="Notes privées sur ce client ou cette facture…"
              rows={5}
              className="mt-3 bg-cream-2/40 border-0 focus:bg-white"
            />
            <p className="mt-2 text-[11.5px] text-ink-3 italic">
              Visibles uniquement par vous. Pas envoyées au client.
            </p>
          </Card>
        </div>
      </div>
    </div>
  );
}

function InvoiceDetailSkeleton() {
  return (
    <div className="flex flex-col gap-6 animate-pulse">
      <div className="h-3 w-20 rounded bg-cream-2" />
      <div className="h-8 w-2/3 rounded bg-cream-2" />
      <div className="h-4 w-1/2 rounded bg-cream-2" />
      <div className="grid grid-cols-1 gap-6 lg:grid-cols-[1.1fr_1fr]">
        <div className="h-[480px] rounded-card bg-cream-2" />
        <div className="flex flex-col gap-4">
          <div className="h-48 rounded-card bg-cream-2" />
          <div className="h-32 rounded-card bg-cream-2" />
          <div className="h-32 rounded-card bg-cream-2" />
        </div>
      </div>
    </div>
  );
}
