import { useMemo, useState } from "react";
import { Check, AlertCircle, ArrowRight, FileText, Calendar } from "lucide-react";
import { toast } from "sonner";

import {
  usePendingCheckins,
  useCheckinPaid,
  useCheckinStillPending,
  type PendingCheckinInvoice,
} from "@/lib/checkin";
import { formatDate, formatDueDelta, formatEuros, isOverdue } from "@/lib/format";
import { cn } from "@/lib/utils";

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/Dialog";
import { Button } from "@/components/ui/Button";

const SESSION_DISMISS_KEY = "rubis.checkin.dismissed";

/**
 * Modale qui se déclenche au login si l'org a des factures en
 * `awaiting_user_confirmation`. Pour chacune, l'user répond directement :
 *   - "Oui, payée"     → mark paid + cancel relances
 *   - "Non, impayée"   → schedule relances + status → in_relance
 *   - "Plus tard"      → on passe à la suivante, on ne touche pas la facture
 *
 * Stratégie de queue : on s'appuie sur le serveur comme source de vérité.
 * Après chaque réponse, l'invoice quitte le statut `awaiting_user_confirmation`
 * et disparaît du refetch. On affiche **toujours queue[0]**, donc la
 * suivante remonte naturellement à la position 0 — pas de cursor à gérer.
 *
 * Pour "Plus tard" (skip), on garde un set local d'IDs ignorés cette
 * session, qu'on filtre côté client (le serveur les retournera toujours
 * tant qu'elles sont awaiting_user_confirmation).
 */
export function InAppCheckinModal() {
  const { data: pending = [], isLoading } = usePendingCheckins();
  const paidMutation = useCheckinPaid();
  const stillPendingMutation = useCheckinStillPending();

  // IDs ignorés cette session (skip "Plus tard"). Persiste en mémoire
  // pendant la vie du composant, perdu au refresh — ce qui est le but :
  // l'user retombe dessus au prochain login.
  const [skipped, setSkipped] = useState<Set<string>>(new Set());

  // sessionStorage flag — true = l'user a explicitement fermé (X), on
  // ne ré-ouvre pas tant qu'il ne reload pas l'onglet.
  const [dismissed, setDismissed] = useState<boolean>(() => {
    if (typeof window === "undefined") return false;
    return sessionStorage.getItem(SESSION_DISMISS_KEY) === "1";
  });

  // Queue = pending serveur, moins les skippés locaux. Ordre serveur
  // (échéance asc) préservé.
  const queue = useMemo<PendingCheckinInvoice[]>(
    () => pending.filter((p) => !skipped.has(p.id)),
    [pending, skipped],
  );
  const current = queue[0];
  const totalSeen = pending.length; // utilisé pour le compteur "X / Y"
  const positionLeft = queue.length;

  const shouldOpen = !isLoading && !dismissed && queue.length > 0;

  const handleClose = () => {
    sessionStorage.setItem(SESSION_DISMISS_KEY, "1");
    setDismissed(true);
  };

  const onPaid = () => {
    if (!current) return;
    paidMutation.mutate(current.id, {
      onSuccess: () => {
        toast.success(`${current.numero} marquée encaissée. + 1 rubis.`);
        // Le refetch va retirer cette invoice de pending — current devient
        // automatiquement la suivante (queue[0]).
      },
      onError: () =>
        toast.error("Impossible de marquer la facture. Réessayez."),
    });
  };

  const onStillPending = () => {
    if (!current) return;
    stillPendingMutation.mutate(current.id, {
      onSuccess: () => {
        toast.success(`Relances activées pour ${current.numero}.`);
      },
      onError: () =>
        toast.error("Impossible de programmer les relances. Réessayez."),
    });
  };

  const onSkip = () => {
    if (!current) return;
    setSkipped((prev) => {
      const next = new Set(prev);
      next.add(current.id);
      return next;
    });
  };

  if (!current) return null;

  const isPending =
    paidMutation.isPending || stillPendingMutation.isPending;
  // Position courante = totalSeen - positionLeft + 1, pour avoir "1/3, 2/3…"
  // même si la queue rétrécit après chaque réponse.
  const cursorLabel = `${totalSeen - positionLeft + 1} / ${totalSeen}`;
  const remaining = positionLeft - 1;

  return (
    <Dialog
      open={shouldOpen}
      onOpenChange={(open) => {
        if (!open) handleClose();
      }}
    >
      <DialogContent maxWidth={520}>
        <DialogHeader>
          <p className="text-[10.5px] uppercase tracking-[0.12em] text-rubis font-semibold">
            Confirmation · {cursorLabel}
          </p>
          <DialogTitle className="mt-1">
            Avez-vous été <em className="text-rubis not-italic">payé</em> sur cette facture ?
          </DialogTitle>
          <DialogDescription className="mt-1.5">
            Aucune relance ne part sans votre validation. Si la facture est
            réglée, on évite l'email inutile et on encaisse +1 rubis.
          </DialogDescription>
        </DialogHeader>

        <InvoiceCard invoice={current} />

        <div className="mt-5 flex flex-col gap-2.5">
          <Button
            size="md"
            variant="primary"
            loading={paidMutation.isPending}
            disabled={isPending}
            onClick={onPaid}
            className="w-full justify-start"
          >
            <Check size={15} aria-hidden="true" />
            Oui — la facture est payée
          </Button>
          <Button
            size="md"
            variant="secondary"
            loading={stillPendingMutation.isPending}
            disabled={isPending}
            onClick={onStillPending}
            className="w-full justify-start"
          >
            <AlertCircle size={15} aria-hidden="true" />
            Non — toujours en attente, lance les relances
          </Button>
        </div>

        <div className="mt-4 flex items-center justify-between">
          <button
            type="button"
            onClick={onSkip}
            disabled={isPending}
            className={cn(
              "text-[12.5px] text-ink-3 hover:text-rubis underline-offset-4 hover:underline cursor-pointer",
              "disabled:opacity-50 disabled:cursor-not-allowed",
            )}
          >
            Plus tard — passer à la suivante
          </button>
          {remaining > 0 && (
            <p className="text-[11.5px] text-ink-3 italic flex items-center gap-1">
              <ArrowRight size={11} aria-hidden="true" />
              {remaining} autre{remaining > 1 ? "s" : ""} après
            </p>
          )}
        </div>
      </DialogContent>
    </Dialog>
  );
}

/** Petite fiche récap de la facture concernée. */
function InvoiceCard({ invoice }: { invoice: PendingCheckinInvoice }) {
  const isLate = isOverdue(invoice.dueDate);
  const dueLabel = formatDueDelta(invoice.dueDate);

  return (
    <div className="rounded-card border border-line bg-white px-4 py-3.5">
      <div className="flex items-start justify-between gap-3 mb-3">
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-2 mb-0.5">
            <FileText size={13} className="text-ink-3 shrink-0" aria-hidden="true" />
            <p className="font-display text-[14px] font-semibold tracking-tight text-ink truncate">
              {invoice.numero}
            </p>
          </div>
          <p className="text-[12.5px] text-ink-2 truncate">{invoice.clientName}</p>
        </div>
      </div>
      <div className="flex items-end justify-between gap-3">
        <p className="font-display text-[22px] font-bold tabular-nums leading-none text-ink">
          {formatEuros(invoice.amountTtcCents)}
        </p>
        <div className="text-right">
          <div className="flex items-center gap-1 justify-end text-[11.5px] text-ink-3 tabular-nums">
            <Calendar size={11} aria-hidden="true" />
            <span>échue le {formatDate(invoice.dueDate)}</span>
          </div>
          <p
            className={cn(
              "mt-0.5 text-[11.5px] font-medium tabular-nums",
              isLate ? "text-rubis-deep" : "text-ink-3",
            )}
          >
            {dueLabel}
          </p>
        </div>
      </div>
      {invoice.planName && (
        <p className="mt-3 pt-3 border-t border-line text-[11.5px] text-ink-3">
          Plan : <strong className="font-medium text-ink-2">{invoice.planName}</strong>
        </p>
      )}
    </div>
  );
}
