"use client";

import { DashboardSection } from "@/components/dashboard-page";
import { DataRefreshControl } from "@/components/data-refresh-control";
import {
  datosEntregaIniciales,
  EntregaForm,
  validarDatosEntrega,
  type DatosEntregaForm,
} from "@/components/ot/entrega-form";
import { useAuth } from "@/components/providers";
import { Badge, type EstadoOT } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import {
  Dialog,
  DialogBody,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { ErrorState } from "@/components/ui/error-state";
import { SkeletonDetailHeader, SkeletonTable } from "@/components/ui/skeleton";
import { useFlagsConfiguracion } from "@/hooks/use-flags-configuracion";
import { useToast } from "@/hooks/use-toast";
import { otsApi, uploadFileWithProgress, whatsappApi } from "@/lib/api";
import {
  canMutateOtRemotely,
  getOtNextEstado,
  isOtLocked,
  OT_DETAIL_REFRESH_INTERVAL_MS,
  refreshOtDetail,
} from "@/lib/ot-detail";
import {
  formatCurrency,
  formatDate,
  formatDateTime,
  getEstadoLabel,
} from "@/lib/utils";
import { normalizePrintAssetUrl, nombreVisibleParaCliente } from "@/lib/print";
import { getSignatureUploadFile } from "@/lib/signature-pad";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
  AlertTriangle,
  ArrowLeft,
  Calendar,
  Camera,
  Check,
  ChevronRight,
  ClipboardList,
  Download,
  Edit,
  Fuel,
  Gauge,
  History,
  Loader2,
  MessageCircle,
  PackageCheck,
  PenTool,
  Printer,
  Receipt,
  Upload,
  User,
  Wrench,
} from "lucide-react";
import Link from "next/link";
import { useParams, useRouter } from "next/navigation";
import { useRef, useState } from "react";
import type SignatureCanvas from "react-signature-canvas";

const ESTADOS_OT: readonly EstadoOT[] = ["borrador", "en_proceso", "cotizada", "aprobada", "terminada", "facturada", "entregada"];

function isEstadoOT(value: string): value is EstadoOT {
  return (ESTADOS_OT as readonly string[]).includes(value);
}

function EstadoOtBadge({ estado }: { estado: string }) {
  if (isEstadoOT(estado)) {
    return (
      <Badge variant="estado" estado={estado}>
        {getEstadoLabel(estado)}
      </Badge>
    );
  }
  return <Badge variant="outline">{getEstadoLabel(estado)}</Badge>;
}

// El color de fondo de cada tarjeta refleja si esa pieza esta pendiente o
// no (amber vs blanco) -- antes era un color fijo por categoria (Firmas
// siempre verde, Daños siempre rosado) sin relacion con el estado real, asi
// que una tarjeta "Firmas" verde podia decir "Pendiente" adentro: colores en
// conflicto con el texto. El color por categoria se conserva solo en el
// icono, para poder distinguir las 4 secciones de un vistazo.
const moduleCards = [
  { label: "Daños", icon: AlertTriangle, tone: "text-destructive", href: "danos" },
  { label: "Fotos", icon: Camera, tone: "text-primary", href: "fotos" },
  { label: "Cotización", icon: Receipt, tone: "text-muted-foreground", href: "cotizacion" },
  { label: "Firmas", icon: PenTool, tone: "text-success", href: "firmas" },
] as const;

const PASOS_TIMELINE = [
  { id: "borrador", label: "Recepción" },
  { id: "cotizada", label: "Cotizado" },
  { id: "aprobada", label: "Aprobado" },
  { id: "en_proceso", label: "En Proceso" },
  { id: "terminada", label: "Terminado" },
  { id: "facturada", label: "Facturado" },
  { id: "entregada", label: "Entregado" },
] as const;

export default function OTDetailPage() {
  const params = useParams();
  const router = useRouter();
  const { toast } = useToast();
  const { user, canRead, canWrite } = useAuth();
  const queryClient = useQueryClient();
  const routeId = String(params.id);
  const pdfInputRef = useRef<HTMLInputElement | null>(null);
  const [pdfProgress, setPdfProgress] = useState(0);
  const [confirmEntregaOpen, setConfirmEntregaOpen] = useState(false);
  const [entrega, setEntrega] = useState<DatosEntregaForm>(() => datosEntregaIniciales(null));
  const [entregaError, setEntregaError] = useState("");
  const firmaEntregaRef = useRef<SignatureCanvas | null>(null);
  const [mostrarBitacora, setMostrarBitacora] = useState(false);
  const flags = useFlagsConfiguracion();
  const canViewLogs = canRead("logs") && flags.usaBitacora;
  const usaWhatsappEstado = flags.usaWhatsapp && flags.usaEstadoPublico;
  const usaFirmas = flags.usaFirmaCliente || flags.usaFirmaRecepcion;

  const { data, dataUpdatedAt, isFetching, isLoading, error, refetch } =
    useQuery({
      queryKey: ["ots", "detail", routeId],
      queryFn: () => refreshOtDetail(routeId),
      enabled: !!routeId,
      refetchInterval: OT_DETAIL_REFRESH_INTERVAL_MS,
      refetchOnReconnect: true,
      refetchOnWindowFocus: true,
    });

  const ot = data?.ot;
  const cliente = data?.cliente;
  const inventario = data?.inventario || [];
  const danos = ot?.danos || [];
  const danosConFoto = danos.filter((dano: any) =>
    Boolean(dano.fotoUrl),
  ).length;
  const zonasDano = Array.from(
    new Set<string>(
      danos.map((dano: any) =>
        String(dano.zona || "Sin zona").replaceAll("_", " "),
      ),
    ),
  ).slice(0, 4);

  const { data: eventos = [] } = useQuery({
    queryKey: ["ots", "eventos", routeId],
    queryFn: () => otsApi.getEventos(Number(ot?.serverId)),
    enabled: canViewLogs && Boolean(ot?.serverId) && navigator.onLine,
    refetchInterval: OT_DETAIL_REFRESH_INTERVAL_MS,
    refetchOnReconnect: true,
    refetchOnWindowFocus: true,
  });

  const estadoFacturable = ot?.estado === "terminada" || ot?.estado === "facturada";
  const {
    data: facturacionPos,
    refetch: refetchFacturacion,
    isFetching: verificandoPago,
  } = useQuery({
    queryKey: ["ots", "facturacion-pos", routeId],
    queryFn: () => otsApi.getFacturacionPos(Number(ot?.serverId)),
    enabled: flags.usaFacturacion && Boolean(ot?.serverId) && navigator.onLine,
    refetchInterval: estadoFacturable ? OT_DETAIL_REFRESH_INTERVAL_MS : false,
  });

  // `aplica` lo calcula el backend (flag de facturación + POS habilitado en la
  // tienda de la OT); sin respuesta, solo una OT ya facturada prueba que aplica.
  const facturacionAplica =
    flags.usaFacturacion &&
    (facturacionPos ? facturacionPos.aplica !== false : ot?.estado === "facturada");
  const relevantParaFacturacion = facturacionAplica && estadoFacturable;
  const tieneFactura = facturacionPos?.transac != null && facturacionPos?.serie != null;
  const exigePago = facturacionAplica && (facturacionPos?.exigePago ?? flags.exigePagoParaEntrega);
  const pagoConfirmado = Boolean(facturacionPos?.pagoConfirmado);
  const pagoPendiente = exigePago && !pagoConfirmado;
  // Lo que dice POSTouch (hdetmed) sobre el pago: el backend lo consulta en cada
  // refresco y, si ya esta liquidado, lo registra solo.
  const pagoPos: string | null = facturacionPos?.pagoPos ?? null;
  const pagoDetectadoEnPos = Boolean(facturacionPos?.pagoDetectadoEnPos);
  const textoPago = pagoConfirmado
    ? pagoDetectadoEnPos
      ? "Pago recibido (verificado en POSTouch)"
      : "Pago confirmado manualmente"
    : pagoPos === "pendiente"
      ? "Pago pendiente de liquidar en POSTouch"
      : pagoPos === "anulada"
        ? "Factura anulada en POSTouch"
        : pagoPos === "no_encontrada" || pagoPos === "desconocido"
          ? "No se pudo verificar el pago en POSTouch"
          : "Verificando pago en POSTouch";

  const invalidarFacturacion = async () => {
    await queryClient.invalidateQueries({ queryKey: ["ots", "detail", routeId] });
    await queryClient.invalidateQueries({ queryKey: ["ots", "facturacion-pos", routeId] });
  };

  const reintentarFacturacionMutation = useMutation({
    mutationFn: async () => {
      const resultado = await otsApi.reintentarFacturacionPos(Number(ot?.serverId));
      if (resultado && resultado.ok === false) {
        throw new Error(
          resultado.error || resultado.message || "POSTouch rechazó la factura sin dar un motivo.",
        );
      }
      return resultado;
    },
    onSuccess: async () => {
      await invalidarFacturacion();
      toast({ variant: "success", title: "Orden facturada en POSTouch" });
    },
    onError: async (error: any) => {
      await invalidarFacturacion();
      toast({
        variant: "destructive",
        title: "No se pudo facturar",
        description: error.message || "Revisa la configuración de facturación POS de la tienda.",
      });
    },
  });

  const confirmarPagoMutation = useMutation({
    mutationFn: () => otsApi.confirmarPago(Number(ot?.serverId)),
    onSuccess: async () => {
      await invalidarFacturacion();
      await queryClient.invalidateQueries({ queryKey: ["ots", "eventos", routeId] });
      toast({ variant: "success", title: "Pago confirmado" });
    },
    onError: (error: any) =>
      toast({
        variant: "destructive",
        title: "No se pudo confirmar el pago",
        description: error.message || "Intenta de nuevo.",
      }),
  });

  const nextEstado = ot ? getOtNextEstado(ot.estado, facturacionAplica) : null;
  const cotizacion = ot?.cotizaciones?.[0] || null;
  const canMutate = canMutateOtRemotely(ot);
  const locked = isOtLocked(ot);
  const hasClienteFirma = Boolean(ot?.firma?.firmaCliente);
  const hasRecepcionFirma = Boolean(ot?.firma?.firmaRecepcion);
  const isDelivering = nextEstado?.next === "entregada";
  const exigeFirmaCliente = flags.usaFirmaCliente;
  const exigeFirmaRecepcion = flags.usaFirmaRecepcion;
  const motivoEntregaBloqueada = !isDelivering
    ? null
    : exigeFirmaCliente && !hasClienteFirma
      ? "Falta la firma del cliente."
      : exigeFirmaRecepcion && !hasRecepcionFirma
        ? "Falta la firma de recepción."
        : pagoPendiente
          ? "Falta el pago: verifícalo en POSTouch."
          : null;
  const canDeliver = motivoEntregaBloqueada === null;

  const abrirEntrega = () => {
    setEntrega(datosEntregaIniciales(ot, nombreVisibleParaCliente(user?.nombre)));
    setEntregaError("");
    setConfirmEntregaOpen(true);
  };

  const refreshQueries = async () => {
    await queryClient.invalidateQueries({ queryKey: ["ots"] });
    await queryClient.invalidateQueries({
      queryKey: ["ots", "detail", routeId],
    });
    await queryClient.invalidateQueries({
      queryKey: ["cotizacion", "ot", routeId],
    });
    await queryClient.invalidateQueries({ queryKey: ["historial"] });
  };

  const changeEstadoMutation = useMutation({
    mutationFn: async () => {
      if (!ot?.serverId || !nextEstado) {
        throw new Error("La OT no está lista para cambiar de estado.");
      }

      if (nextEstado.next === "entregada" && exigeFirmaCliente && !hasClienteFirma) {
        throw new Error(
          "Captura la firma del cliente antes de entregar el vehículo.",
        );
      }

      if (nextEstado.next === "entregada" && exigeFirmaRecepcion && !hasRecepcionFirma) {
        throw new Error(
          "Captura la firma de recepción antes de entregar el vehículo.",
        );
      }

      if (nextEstado.next === "entregada" && pagoPendiente) {
        throw new Error(
          pagoPos === "anulada"
            ? "La factura está anulada en POSTouch: no se puede entregar el vehículo."
            : "El pago aún no figura liquidado en POSTouch. Verifícalo antes de entregar el vehículo.",
        );
      }

      if (
        nextEstado.next === "cotizada" &&
        !(ot.cotizaciones || []).some((item: any) => (item.lineas || []).length > 0)
      ) {
        throw new Error(
          "No se puede marcar como cotizada sin al menos una cotización con productos o servicios agregados.",
        );
      }

      if (nextEstado.next !== "entregada") {
        return otsApi.changeEstado(Number(ot.serverId), nextEstado.next);
      }

      const motivo = validarDatosEntrega(entrega, {
        exigeFirma: flags.usaFirmaRecepcion,
        hayFirma: Boolean(firmaEntregaRef.current && !firmaEntregaRef.current.isEmpty()),
      });
      if (motivo) {
        setEntregaError(motivo);
        throw new Error(motivo);
      }
      setEntregaError("");

      let firmaEntrega: string | undefined;
      if (flags.usaFirmaRecepcion && firmaEntregaRef.current && !firmaEntregaRef.current.isEmpty()) {
        const file = await getSignatureUploadFile(firmaEntregaRef, `firma-entrega-${Date.now()}`);
        const uploaded = await uploadFileWithProgress(file, "firma", () => undefined);
        firmaEntrega = uploaded.url;
      }

      return otsApi.changeEstado(
        Number(ot.serverId),
        nextEstado.next,
        // La fecha de salida es el momento real de la entrega, no se elige a mano.
        new Date().toISOString(),
        {
          kmSalida: Number(entrega.kmSalida),
          nivelGasolinaSalida: entrega.nivelGasolinaSalida,
          recomendacionesEntrega: entrega.recomendaciones.trim(),
          entregadoPor: entrega.entregadoPor.trim(),
          firmaEntrega,
        },
      );
    },
    onSuccess: async () => {
      setConfirmEntregaOpen(false);
      await refreshQueries();
      toast({
        variant: "success",
        title: "Estado actualizado",
        description: "La OT avanzó al siguiente paso.",
      });
    },
    onError: (mutationError: any) => {
      toast({
        variant: "destructive",
        title: "Error",
        description: mutationError.message || "Error al actualizar el estado",
      });
    },
  });

  const uploadPdfMutation = useMutation({
    mutationFn: async (file: File) => {
      if (!ot?.serverId) {
        throw new Error("Primero guarda la OT para usar esta acción.");
      }

      setPdfProgress(0);
      const uploaded = await uploadFileWithProgress(
        file,
        "pdf",
        setPdfProgress,
      );
      return otsApi.savePdfEscaner(Number(ot.serverId), uploaded.url);
    },
    onSuccess: async () => {
      setPdfProgress(100);
      await refreshQueries();
      toast({
        variant: "success",
        title: "PDF guardado",
        description: "El documento ya quedo adjunto a la OT.",
      });
    },
    onError: (mutationError: any) => {
      setPdfProgress(0);
      toast({
        variant: "destructive",
        title: "Error",
        description: mutationError.message || "No se pudo guardar el PDF",
      });
    },
  });

  const whatsappEstadoMutation = useMutation({
    mutationFn: async () => {
      if (!ot?.serverId) {
        throw new Error("La OT no está sincronizada.");
      }
      return whatsappApi.sendEstadoOt(Number(ot.serverId));
    },
    onSuccess: async () => {
      await queryClient.invalidateQueries({
        queryKey: ["ots", "eventos", routeId],
      });
      toast({
        variant: "success",
        title: "WhatsApp enviado",
        description: "El cliente recibió el link para revisar el estado.",
      });
    },
    onError: (mutationError: any) => {
      toast({
        variant: "destructive",
        title: "Error",
        description: mutationError.message || "No se pudo enviar el WhatsApp",
      });
    },
  });

  if (isLoading) {
    return (
      <div className="min-h-full pb-16 md:pb-10">
        <main className="mx-auto flex max-w-7xl flex-col gap-6">
          <Card className="overflow-hidden">
            <CardContent className="space-y-5 p-5 md:p-6">
              <SkeletonDetailHeader />
              <SkeletonTable rows={3} columns={4} className="p-0" />
            </CardContent>
          </Card>
        </main>
      </div>
    );
  }

  if (error || !ot) {
    return (
      <div className="flex min-h-[60dvh] items-center justify-center p-4">
        <ErrorState
          title={error ? "No se pudo cargar la OT" : "OT no encontrada"}
          description={
            error
              ? "No logramos comunicarnos con el servidor. Revisa la conexión e intenta de nuevo."
              : "No logramos encontrar la orden de trabajo solicitada."
          }
          onRetry={() => (error ? refetch() : router.push("/dashboard/ots"))}
          retryLabel={error ? "Reintentar" : "Volver al listado"}
        />
      </div>
    );
  }

  return (
    <div className="min-h-full pb-16 md:pb-10">
      <main className="mx-auto flex max-w-7xl flex-col gap-6">
        <Card className="overflow-hidden">
          <CardContent className="space-y-5 p-5 md:p-6">
            <div className="flex flex-col gap-4 xl:flex-row xl:items-start xl:justify-between">
              <div className="flex items-start gap-3 md:gap-4">
                <Button
                  variant="outline"
                  size="icon"
                  aria-label="Volver al listado de OTs"
                  onClick={() => router.push("/dashboard/ots")}
                >
                  <ArrowLeft className="h-4 w-4" />
                </Button>
                <div>
                  <div className="flex flex-wrap items-center gap-2">
                    <h1 className="text-2xl font-bold tracking-tight text-foreground md:text-3xl">
                      {ot.numeroOt}
                    </h1>
                    <EstadoOtBadge estado={ot.estado} />
                    {locked ? <Badge variant="success">OT bloqueada</Badge> : null}
                  </div>
                  <p className="mt-2 text-sm text-muted-foreground">
                    {ot.vehiculo?.placa || "Sin placa"} |{" "}
                    {formatDate(ot.fechaEntrada)}
                  </p>
                  <p className="mt-1 text-sm text-muted-foreground">
                    {cliente?.nombre || ot.clienteTarjeta}
                  </p>
                  {flags.usaMecanicos ? (
                    <p className="mt-1 text-sm font-semibold text-foreground">
                      Mecanico: {ot.mecanico?.nombre || "Sin asignar"}
                    </p>
                  ) : null}
                </div>
              </div>

              <div className="flex flex-wrap gap-2">
                <DataRefreshControl
                  updatedAt={dataUpdatedAt}
                  isFetching={isFetching}
                  onRefresh={() => void refetch()}
                />
                {flags.imprimeRecepcion ? (
                  <Link
                    href={`/dashboard/ots/${routeId}/imprimir/recepcion`}
                    target="_blank"
                  >
                    <Button variant="outline">
                      <Printer className="mr-2 h-4 w-4" />
                      Imprimir recepción
                    </Button>
                  </Link>
                ) : null}
                {flags.imprimeCotizacion ? (
                  <Link
                    href={`/dashboard/ots/${routeId}/imprimir/cotizacion`}
                    target="_blank"
                  >
                    <Button variant="outline">
                      <Printer className="mr-2 h-4 w-4" />
                      Imprimir cotización
                    </Button>
                  </Link>
                ) : null}
                {flags.imprimeOrdenInterna ? (
                  <Link
                    href={`/dashboard/ots/${routeId}/imprimir/orden-interna`}
                    target="_blank"
                  >
                    <Button
                      variant="outline"
                      className="rounded-xl border-border bg-surface"
                    >
                      <ClipboardList className="mr-2 h-4 w-4" />
                      Orden interna
                    </Button>
                  </Link>
                ) : null}
                {flags.imprimeEntrega ? (
                  <Link
                    href={`/dashboard/ots/${routeId}/imprimir/entrega`}
                    target="_blank"
                  >
                    <Button
                      variant="outline"
                      className="rounded-xl border-border bg-surface"
                    >
                      <PackageCheck className="mr-2 h-4 w-4" />
                      Imprimir entrega
                    </Button>
                  </Link>
                ) : null}
                {usaWhatsappEstado ? (
                  <Button
                    variant="outline"
                    className="text-success [@media(hover:hover)]:hover:bg-success-soft"
                    onClick={() => whatsappEstadoMutation.mutate()}
                    disabled={!canMutate || whatsappEstadoMutation.isPending}
                  >
                    {whatsappEstadoMutation.isPending ? (
                      <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                    ) : (
                      <MessageCircle className="mr-2 h-4 w-4" />
                    )}
                    WhatsApp estado
                  </Button>
                ) : null}
                <Link href={`/dashboard/ots/${routeId}/cotizacion`}>
                  <Button variant="outline">Cotización</Button>
                </Link>
                <Link href={`/dashboard/ots/${routeId}/editar`}>
                  <Button variant="outline">
                    <Edit className="mr-2 h-4 w-4" />
                    Editar
                  </Button>
                </Link>
                {flags.usaPdfEscaner ? (
                  <Button
                    variant="outline"
                    onClick={() => pdfInputRef.current?.click()}
                    disabled={!canMutate || uploadPdfMutation.isPending}
                  >
                    {uploadPdfMutation.isPending ? (
                      <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                    ) : (
                      <Upload className="mr-2 h-4 w-4" />
                    )}
                    {canMutate ? "Adjuntar PDF" : "No disponible"}
                  </Button>
                ) : null}
                {canViewLogs ? (
                  <Button
                    variant="outline"
                    onClick={() => setMostrarBitacora(true)}
                  >
                    <History className="mr-2 h-4 w-4" />
                    Ver bitácora
                  </Button>
                ) : null}
              </div>
            </div>

            {/* TIMELINE VISUAL FASE 5 */}
            <div className="py-6">
              <div className="relative flex items-center justify-between">
                <div className="absolute left-0 top-1/2 hidden h-1 w-full -translate-y-1/2 bg-muted md:block" />
                {PASOS_TIMELINE.filter(
                  (step) => step.id !== "facturada" || facturacionAplica,
                ).map((step, index, array) => {
                  const estadoEnLinea = ot.estado === "facturada" && !facturacionAplica ? "terminada" : ot.estado;
                  const stateIndex = array.findIndex((s) => s.id === estadoEnLinea);
                  const isCompleted = index <= stateIndex;
                  const isCurrent = index === stateIndex;

                  return (
                    <div
                      key={step.id}
                      className="relative z-10 flex flex-col items-center gap-2"
                    >
                      <div
                        className={`flex h-10 w-10 items-center justify-center rounded-full border-4 transition-[background-color,border-color,color,transform] duration-150 ease-out ${
                          isCurrent
                            ? "scale-110 border-primary bg-primary text-primary-foreground shadow-md"
                            : isCompleted
                              ? "border-transparent bg-success text-success-foreground"
                              : "border-border bg-surface text-subtle-foreground"
                        }`}
                      >
                        {isCompleted && !isCurrent ? (
                          <Check strokeWidth={3} size={20} />
                        ) : (
                          <span className="text-sm font-bold">{index + 1}</span>
                        )}
                      </div>
                      <span
                        className={`hidden text-xs font-bold uppercase tracking-wider md:block ${
                          isCurrent
                            ? "text-primary"
                            : isCompleted
                              ? "text-success"
                              : "text-subtle-foreground"
                        }`}
                      >
                        {step.label}
                      </span>
                    </div>
                  );
                })}
              </div>
            </div>

            {relevantParaFacturacion ? (
              tieneFactura ? (
                <div className="flex flex-wrap items-center gap-2 rounded-xl border border-primary/30 bg-primary-soft px-4 py-3 text-sm text-primary">
                  <Receipt className="h-4 w-4 shrink-0" />
                  <span className="font-bold">Facturado en POSTouch</span>
                  <span className="text-primary">
                    Tienda {facturacionPos.tienda} · Caja {facturacionPos.caja} · {facturacionPos.tipo}{" "}
                    {facturacionPos.serie}-{facturacionPos.transac}
                  </span>
                </div>
              ) : (
                <div className="flex flex-wrap items-center justify-between gap-3 rounded-xl border border-warning/30 bg-warning-soft px-4 py-3 text-sm text-warning">
                  <span className="flex items-center gap-2 font-bold">
                    <AlertTriangle className="h-4 w-4 shrink-0" />
                    No se ha facturado en POSTouch todavía
                  </span>
                  {canMutate && ot.estado === "terminada" ? (
                    <Button
                      variant="outline"
                      size="sm"
                      disabled={reintentarFacturacionMutation.isPending}
                      onClick={() => reintentarFacturacionMutation.mutate()}
                    >
                      {reintentarFacturacionMutation.isPending ? (
                        <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                      ) : (
                        <Receipt className="mr-2 h-4 w-4" />
                      )}
                      Reintentar factura
                    </Button>
                  ) : null}
                </div>
              )
            ) : null}

            <div className="grid gap-3 grid-cols-2 xl:grid-cols-4">
              {moduleCards
                .filter((item) =>
                  item.href === "danos"
                    ? flags.usaDanos
                    : item.href === "fotos"
                      ? flags.usaFotos
                      : item.href === "firmas"
                        ? usaFirmas
                        : true,
                )
                .map((item) => {
                const count =
                  item.href === "danos"
                    ? ot.danos?.length || 0
                    : item.href === "fotos"
                      ? ot.fotos?.length || 0
                      : item.href === "firmas"
                        ? Number(
                            Boolean(
                              ot.firma?.firmaCliente ||
                              ot.firma?.firmaRecepcion,
                            ),
                          )
                        : cotizacion?.lineas?.length || 0;

                const pending = count === 0;

                return (
                  <Link
                    key={item.href}
                    href={`/dashboard/ots/${routeId}/${item.href}`}
                    className="block h-full active:scale-[0.98]"
                  >
                    <Card
                      className={`group h-full transition-[transform,box-shadow] duration-150 ease-out [@media(hover:hover)]:hover:-translate-y-0.5 [@media(hover:hover)]:hover:shadow-md ${
                        pending ? "border-warning/40 bg-warning-soft" : ""
                      }`}
                    >
                      <CardContent className="p-5">
                        <div className="flex items-start justify-between gap-3">
                          <span
                            className={`flex h-14 w-14 items-center justify-center rounded-xl bg-surface shadow-sm ${item.tone}`}
                          >
                            <item.icon className="h-7 w-7" />
                          </span>
                          <ChevronRight className="h-5 w-5 text-subtle-foreground transition-transform duration-150 ease-out group-hover:translate-x-1" />
                        </div>
                        <p className="mt-4 text-lg font-bold text-foreground">
                          {item.label}
                        </p>
                        <div className="mt-1">
                          <Badge variant={pending ? "warning" : "success"}>
                            {pending ? "Pendiente" : `${count} registro${count === 1 ? "" : "s"}`}
                          </Badge>
                        </div>
                      </CardContent>
                    </Card>
                  </Link>
                );
              })}
            </div>

            {nextEstado ? (
              <div className="rounded-xl border border-primary/30 bg-primary-soft/90 p-4">
                <div className="grid gap-4 xl:grid-cols-[1fr_auto] xl:items-end">
                  <div className="space-y-3">
                    <div>
                      <p className="text-sm font-semibold text-primary">
                        Siguiente paso
                      </p>
                    </div>

                    {nextEstado.next === "entregada" ? (
                      <div className="grid gap-4 md:grid-cols-[minmax(0,280px)_1fr]">
                        <div className="space-y-2">
                          <p className="text-sm font-medium text-foreground">
                            Fecha de salida
                          </p>
                          <p className="text-sm text-muted-foreground">
                            Se registra sola con la fecha y hora en que entregas el vehículo.
                          </p>
                        </div>
                        <div className="rounded-xl border border-primary/30 bg-surface p-3">
                          <p className="text-xs font-semibold uppercase tracking-wider text-primary">
                            Antes de entregar
                          </p>
                          <div className="mt-3 grid gap-2 text-sm">
                            {exigeFirmaCliente ? (
                              <div
                                className={`flex items-center gap-2 ${hasClienteFirma ? "text-success" : "text-warning"}`}
                              >
                                <Check className="h-4 w-4" />
                                Firma del cliente
                              </div>
                            ) : null}
                            {exigeFirmaRecepcion ? (
                              <div
                                className={`flex items-center gap-2 ${hasRecepcionFirma ? "text-success" : "text-warning"}`}
                              >
                                <Check className="h-4 w-4" />
                                Firma de recepción
                              </div>
                            ) : null}
                            {exigePago ? (
                              <div
                                className={`flex items-center gap-2 ${pagoConfirmado ? "text-success" : "text-warning"}`}
                              >
                                <Check className="h-4 w-4" />
                                {textoPago}
                              </div>
                            ) : null}
                          </div>
                          {(exigeFirmaCliente && !hasClienteFirma) ||
                          (exigeFirmaRecepcion && !hasRecepcionFirma) ? (
                            <Link
                              href={`/dashboard/ots/${routeId}/firmas`}
                              className="mt-3 inline-flex text-sm font-semibold text-primary hover:underline"
                            >
                              Capturar firmas
                            </Link>
                          ) : null}
                          {pagoPendiente ? (
                            <div className="mt-3 flex flex-wrap items-center gap-2">
                              <Button
                                variant="outline"
                                size="sm"
                                disabled={verificandoPago}
                                onClick={() => refetchFacturacion()}
                              >
                                {verificandoPago ? (
                                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                                ) : (
                                  <Check className="mr-2 h-4 w-4" />
                                )}
                                Verificar pago en POSTouch
                              </Button>
                              {/* Respaldo: solo si POSTouch no se puede leer o el pago
                                  se cobro por otra via; una factura anulada nunca. */}
                              {pagoPos !== "anulada" && canWrite("confirmarPago") ? (
                                <Button
                                  variant="ghost"
                                  size="sm"
                                  disabled={!canMutate || confirmarPagoMutation.isPending}
                                  onClick={() => confirmarPagoMutation.mutate()}
                                >
                                  {confirmarPagoMutation.isPending ? (
                                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                                  ) : null}
                                  Confirmar manualmente
                                </Button>
                              ) : null}
                            </div>
                          ) : null}
                        </div>
                      </div>
                    ) : null}
                  </div>

                  <div className="flex flex-col gap-2 xl:items-end">
                    <Button
                      className="h-11 px-5"
                      onClick={() => {
                        if (isDelivering) {
                          abrirEntrega();
                          return;
                        }
                        changeEstadoMutation.mutate();
                      }}
                      disabled={
                        changeEstadoMutation.isPending ||
                        !canMutate ||
                        !canDeliver
                      }
                    >
                      {changeEstadoMutation.isPending ? (
                        <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                      ) : (
                        <Wrench className="mr-2 h-4 w-4" />
                      )}
                      {canMutate ? nextEstado.label : "No disponible"}
                    </Button>
                    {canMutate && motivoEntregaBloqueada ? (
                      <p className="text-sm font-medium text-warning">
                        {motivoEntregaBloqueada}
                      </p>
                    ) : null}
                  </div>
                </div>
              </div>
            ) : null}
          </CardContent>
        </Card>

        <div className="grid gap-6 xl:grid-cols-[1.35fr_0.9fr]">
          <div className="space-y-6">
            <DashboardSection
              title="Vehículo"
              description="Ficha principal para confirmar unidad, kilometraje y combustible antes de avanzar."
            >
              <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
                <div className="min-w-0 rounded-xl border border-border bg-muted p-4">
                  <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
                    Placa
                  </p>
                  <p className="mt-2 break-all text-xl font-bold text-foreground md:text-2xl">
                    {ot.vehiculo?.placa || "-"}
                  </p>
                </div>
                <div className="rounded-xl border border-border bg-muted p-4">
                  <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
                    Marca / modelo
                  </p>
                  <p className="mt-2 text-base font-bold text-foreground">
                    {ot.vehiculo?.marca || "-"} {ot.vehiculo?.modelo || ""}
                  </p>
                </div>
                <div className="rounded-xl border border-border bg-muted p-4">
                  <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
                    Año
                  </p>
                  <p className="mt-2 text-base font-bold text-foreground">
                    {ot.vehiculo?.anio || "-"}
                  </p>
                </div>
                <div className="rounded-xl border border-border bg-muted p-4">
                  <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
                    Color / serie motor
                  </p>
                  <p className="mt-2 text-base font-bold text-foreground">
                    {ot.vehiculo?.color || "-"}{" "}
                    {ot.vehiculo?.motor ? `| ${ot.vehiculo.motor}` : ""}
                  </p>
                </div>
              </div>
              <div className="mt-4 grid gap-4 md:grid-cols-2">
                <div className="flex items-center gap-4 rounded-xl border border-border bg-surface p-4">
                  <Gauge className="h-6 w-6 text-subtle-foreground" />
                  <div>
                    <p className="text-sm text-muted-foreground">Kilometraje</p>
                    <p className="text-2xl font-bold text-foreground">
                      {Number(ot.km || 0).toLocaleString()} km
                    </p>
                  </div>
                </div>
                <div className="rounded-xl border border-border bg-surface p-4">
                  <div className="flex items-center gap-4">
                    <Fuel className="h-6 w-6 text-subtle-foreground" />
                    <div className="flex-1">
                      <p className="text-sm text-muted-foreground">Combustible</p>
                      <p className="text-2xl font-bold text-foreground">
                        {ot.nivelGasolina}%
                      </p>
                    </div>
                  </div>
                  <div className="mt-3 h-3 overflow-hidden rounded-full bg-muted">
                    <div
                      className={`h-full rounded-full transition-[width] duration-150 ease-out ${Number(ot.nivelGasolina || 0) <= 20 ? "bg-destructive" : Number(ot.nivelGasolina || 0) <= 50 ? "bg-warning" : "bg-success"}`}
                      style={{
                        width: `${Math.min(100, Number(ot.nivelGasolina || 0))}%`,
                      }}
                    />
                  </div>
                </div>
              </div>
            </DashboardSection>

            {ot.requerimientoCliente ? (
              <DashboardSection title="Solicitud del cliente" description="">
                <p className="whitespace-pre-wrap text-sm leading-7 text-foreground">
                  {ot.requerimientoCliente}
                </p>
              </DashboardSection>
            ) : null}

            {ot.observaciones ? (
              <DashboardSection title="Observaciones" description="">
                <p className="whitespace-pre-wrap text-sm leading-7 text-foreground">
                  {ot.observaciones}
                </p>
              </DashboardSection>
            ) : null}
          </div>

          <div className="space-y-6">
            <DashboardSection title="Cliente" description="">
              <div className="space-y-4">
                <div className="rounded-xl border border-border bg-muted p-4">
                  <div className="flex items-center gap-2 text-foreground">
                    <User className="h-4 w-4" />
                    <span className="font-semibold">Cliente</span>
                  </div>
                  <p className="mt-3 text-lg font-bold text-foreground">
                    {cliente?.nombre || ot.clienteTarjeta}
                  </p>
                  <p className="mt-1 text-sm text-muted-foreground">
                    Tarjeta: {ot.clienteTarjeta}
                  </p>
                  {flags.usaHistorial ? (
                    <Link
                      href={`/dashboard/historial?cliente=${ot.clienteTarjeta}`}
                      className="mt-3 inline-flex text-sm font-semibold text-primary hover:underline"
                    >
                      Ver historial del cliente
                    </Link>
                  ) : null}
                </div>

                <div className="rounded-xl border border-border bg-muted p-4">
                  <div className="flex items-center gap-2 text-foreground">
                    <Calendar className="h-4 w-4" />
                    <span className="font-semibold">Fechas</span>
                  </div>
                  <div className="mt-3 space-y-3 text-sm text-muted-foreground">
                    <div>
                      <p className="text-muted-foreground">Entrada</p>
                      <p className="font-semibold text-foreground">
                        {formatDateTime(ot.fechaEntrada)}
                      </p>
                    </div>
                    <div>
                      <p className="text-muted-foreground">Salida</p>
                      <p className="font-semibold text-foreground">
                        {ot.fechaSalida
                          ? formatDateTime(ot.fechaSalida)
                          : "Pendiente"}
                      </p>
                    </div>
                  </div>
                </div>
              </div>
            </DashboardSection>

            {flags.usaCosasTrae || (flags.usaDanos && danos.length > 0) ? (
            <DashboardSection
              title="Inventario e inspeccion"
              description="Objetos recibidos al ingresar la unidad. Los conteos de daños/fotos/firmas ya están arriba, en las tarjetas de módulos."
            >
              <div className="space-y-4">
                {flags.usaCosasTrae ? (
                <div className="rounded-xl border border-border bg-surface p-4">
                  <div className="flex items-center gap-2 text-foreground">
                    <ClipboardList className="h-4 w-4" />
                    <span className="font-semibold">Inventario</span>
                  </div>
                  {inventario.length > 0 ? (
                    <div className="mt-3 flex flex-wrap gap-2">
                      {inventario.map((item: string) => (
                        <span
                          key={item}
                          className="rounded-full bg-primary-soft px-3 py-1 text-sm font-medium text-primary"
                        >
                          {item}
                        </span>
                      ))}
                    </div>
                  ) : (
                    <p className="mt-3 text-sm text-muted-foreground">
                      No hay elementos registrados.
                    </p>
                  )}
                </div>
                ) : null}

                {flags.usaDanos && danos.length > 0 ? (
                  <div className="rounded-xl border border-destructive/20 bg-destructive-soft p-4">
                    <div className="flex flex-wrap items-center justify-between gap-3">
                      <div className="flex items-center gap-2 font-semibold text-destructive">
                        <AlertTriangle className="h-4 w-4" />
                        Resumen de daños
                      </div>
                      <Badge variant="destructive">{danosConFoto}/{danos.length} con foto</Badge>
                    </div>
                    <div className="mt-3 flex flex-wrap gap-2">
                      {zonasDano.map((zona) => (
                        <span
                          key={zona}
                          className="rounded-full bg-surface px-3 py-1 text-xs font-semibold capitalize text-foreground"
                        >
                          {zona}
                        </span>
                      ))}
                      {danos.length > zonasDano.length ? (
                        <span className="rounded-full bg-surface px-3 py-1 text-xs font-semibold text-muted-foreground">
                          +{danos.length - zonasDano.length} más
                        </span>
                      ) : null}
                    </div>
                    {danosConFoto < danos.length ? (
                      <p className="mt-3 text-sm font-medium text-warning">
                        {danos.length - danosConFoto} daño(s) no tienen foto
                        principal.
                      </p>
                    ) : null}
                  </div>
                ) : null}
              </div>
            </DashboardSection>
            ) : null}

            <DashboardSection
              title="Cotización"
              description="Resumen económico de la orden y acceso directo a la cotización."
            >
              {cotizacion ? (
                <div className="space-y-4">
                  <div className="grid gap-3 sm:grid-cols-2">
                    <div className="rounded-xl border border-border bg-muted p-4">
                      <p className="text-sm text-muted-foreground">Lineas</p>
                      <p className="mt-2 text-xl font-bold text-foreground">
                        {cotizacion.lineas?.length || 0}
                      </p>
                    </div>
                    <div className="rounded-xl border border-border bg-muted p-4">
                      <p className="text-sm text-muted-foreground">Total</p>
                      <p className="mt-2 text-xl font-bold text-primary">
                        {formatCurrency(Number(cotizacion.total || 0))}
                      </p>
                    </div>
                  </div>
                  <div className="flex flex-wrap items-center justify-between gap-3 rounded-xl border border-border bg-surface p-4">
                    <div>
                      <p className="text-sm font-semibold text-foreground">
                        {cotizacion.numeroCotizacion ||
                          "Cotización en borrador"}
                      </p>
                      <p className="mt-1 text-sm capitalize text-muted-foreground">
                        Estado: {cotizacion.estado || "borrador"}
                      </p>
                    </div>
                    <Link href={`/dashboard/ots/${routeId}/cotizacion`}>
                      <Button variant="outline">
                        Abrir cotización
                      </Button>
                    </Link>
                  </div>
                </div>
              ) : (
                <div className="rounded-xl border border-dashed border-border-strong bg-muted p-5">
                  <p className="text-sm text-muted-foreground">
                    Todavía no hay una cotización creada para esta orden.
                  </p>
                  <Link href={`/dashboard/ots/${routeId}/cotizacion`}>
                    <Button variant="outline" className="mt-4">
                      Crear cotización
                    </Button>
                  </Link>
                </div>
              )}
            </DashboardSection>

            {flags.usaPdfEscaner ? (
            <DashboardSection
              title="Documento escaneado"
              description="PDF y evidencia documental dentro del flujo de la OT."
            >
              <div className="space-y-4">
                {ot.pdfEscaner ? (
                  <a
                    href={normalizePrintAssetUrl(ot.pdfEscaner)}
                    target="_blank"
                    rel="noopener noreferrer"
                    className="flex items-center justify-center gap-2 rounded-xl border border-border bg-muted p-4 text-sm font-semibold text-foreground transition-colors hover:bg-muted"
                  >
                    <Download className="h-4 w-4" />
                    Abrir PDF actual
                  </a>
                ) : (
                  <div className="rounded-xl border border-dashed border-border-strong bg-muted p-4 text-sm text-muted-foreground">
                    Todavía no hay PDF adjunto.
                  </div>
                )}

                {uploadPdfMutation.isPending ? (
                  <div className="rounded-xl border border-border bg-surface p-4">
                    <div className="flex items-center justify-between gap-3 text-sm text-muted-foreground">
                      <span>Subiendo documento</span>
                      <span>{pdfProgress}%</span>
                    </div>
                    <div className="mt-3 h-2 overflow-hidden rounded-full bg-muted">
                      <div
                        className="h-full rounded-full bg-primary transition-[width] duration-150 ease-out"
                        style={{ width: `${pdfProgress}%` }}
                      />
                    </div>
                  </div>
                ) : null}
              </div>
            </DashboardSection>
            ) : null}

          </div>
        </div>
      </main>

      {flags.usaPdfEscaner ? (
        <input
          ref={pdfInputRef}
          type="file"
          accept="application/pdf"
          className="hidden"
          onChange={(event) => {
            const file = event.target.files?.[0];
            if (file) uploadPdfMutation.mutate(file);
            event.currentTarget.value = "";
          }}
        />
      ) : null}

      {/*
        "Ver bitácora" vivía como una sección más de la página, al fondo del
        todo -- al hacer clic no pasaba nada visible (el botón está arriba,
        la sección aparecía mucho más abajo del scroll), como si el botón no
        hiciera nada. Un diálogo reacciona en el momento, sin importar en
        qué parte de la página esté el botón que lo abre.
      */}
      <Dialog open={mostrarBitacora && canViewLogs} onOpenChange={setMostrarBitacora}>
        <DialogContent className="sm:max-w-lg">
          <DialogHeader>
            <DialogTitle>Bitácora de la recepción</DialogTitle>
            <DialogDescription>
              Eventos importantes registrados durante el trabajo.
            </DialogDescription>
          </DialogHeader>
          <DialogBody>
            {eventos.length > 0 ? (
              <div className="space-y-3">
                {eventos.slice(0, 8).map((evento: any) => (
                  <div
                    key={evento.id}
                    className="rounded-xl border border-border bg-muted p-4"
                  >
                    <div className="flex items-start gap-3">
                      <span className="mt-0.5 flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-surface text-primary shadow-sm">
                        <History className="h-4 w-4" />
                      </span>
                      <div className="min-w-0 flex-1">
                        <div className="flex flex-wrap items-center gap-2">
                          <p className="text-sm font-bold text-foreground">
                            {evento.descripcion || "Evento registrado"}
                          </p>
                          <span className="rounded-full bg-surface px-2.5 py-1 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
                            {evento.tipo || "evento"}
                          </span>
                        </div>
                        <p className="mt-1 text-xs text-muted-foreground">
                          {evento.createdAt
                            ? formatDateTime(evento.createdAt)
                            : "Fecha no registrada"}
                          {evento.usuario?.nombre || evento.usuario?.username
                            ? ` | ${evento.usuario?.nombre || evento.usuario?.username}`
                            : evento.usuarioId
                              ? ` | Usuario ${evento.usuarioId}`
                              : ""}
                        </p>
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            ) : (
              <div className="rounded-xl border border-dashed border-border-strong bg-muted p-4 text-sm text-muted-foreground">
                No hay eventos registrados todavía.
              </div>
            )}
          </DialogBody>
        </DialogContent>
      </Dialog>

      <Dialog open={confirmEntregaOpen} onOpenChange={setConfirmEntregaOpen}>
        <DialogContent className="sm:max-w-lg">
          <DialogHeader>
            <DialogTitle>Confirmar entrega del vehículo</DialogTitle>
            <DialogDescription>
              Vas a marcar esta recepción como entregada. Después de confirmar,
              la orden quedará bloqueada para cambios.
            </DialogDescription>
          </DialogHeader>
          <DialogBody className="space-y-3 text-sm">
            <div className="rounded-xl bg-muted p-4">
              <p className="font-semibold text-foreground">{ot.numeroOt}</p>
              <p className="mt-1 text-muted-foreground">
                {ot.vehiculo?.placa || "Sin placa"} |{" "}
                {cliente?.nombre || ot.clienteTarjeta}
              </p>
            </div>
            <div className="grid gap-2">
              {exigeFirmaCliente ? (
                <div className="flex items-center gap-2 text-success">
                  <Check className="h-4 w-4" />
                  Firma del cliente capturada
                </div>
              ) : null}
              {exigeFirmaRecepcion ? (
                <div className="flex items-center gap-2 text-success">
                  <Check className="h-4 w-4" />
                  Firma de recepción capturada
                </div>
              ) : null}
              {exigePago ? (
                <div className="flex items-center gap-2 text-success">
                  <Check className="h-4 w-4" />
                  Pago confirmado
                </div>
              ) : null}
            </div>
            <EntregaForm
              datos={entrega}
              onChange={(datos) => {
                setEntrega(datos);
                setEntregaError("");
              }}
              kmEntrada={ot.km}
              gasolinaEntrada={Number(ot.nivelGasolina || 0)}
              usaFirma={flags.usaFirmaRecepcion}
              firmaRef={firmaEntregaRef}
              onFirmaChange={() => setEntregaError("")}
            />
            {entregaError ? (
              <div className="rounded-xl border border-destructive/20 bg-destructive-soft px-4 py-3 text-sm font-medium text-destructive">
                {entregaError}
              </div>
            ) : null}
          </DialogBody>
          <DialogFooter>
            <Button
              variant="outline"
              size="lg"
              onClick={() => setConfirmEntregaOpen(false)}
            >
              Revisar de nuevo
            </Button>
            <Button
              size="lg"
              disabled={changeEstadoMutation.isPending}
              onClick={() => changeEstadoMutation.mutate()}
            >
              {changeEstadoMutation.isPending ? (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              ) : (
                <Check className="mr-2 h-4 w-4" />
              )}
              Entregar vehículo
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
