import { Icon } from "@iconify/react";
import {
  Alert,
  Box,
  Button,
  Card,
  CardContent,
  Chip,
  Collapse,
  CircularProgress,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  Divider,
  FormControl,
  Grid,
  IconButton,
  InputAdornment,
  InputLabel,
  MenuItem,
  Pagination,
  Paper,
  Select,
  Skeleton,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  TextField,
  Tooltip,
  Typography,
  useMediaQuery,
  useTheme,
} from "@mui/material";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useNavigate, useSearchParams } from "react-router-dom";
import { toast } from "sonner";
import { getEmpresaMonedas } from "../../../api/monedas.service";
import { getMediosPagoActivos } from "../../../api/pagos.service";
import {
  aprobarOrdenPagoProveedor,
  anularOrdenPagoProveedor,
  createOrdenPagoProveedor,
  ejecutarOrdenPagoProveedor,
  enviarAprobacionOrdenPagoProveedor,
  getConfigCompras,
  getCuentasPendientesProveedor,
  getOrdenPagoProveedorPdf,
  getPagoProveedorById,
  getPagosProveedor,
  getPagosProveedorDashboard,
  rechazarOrdenPagoProveedor,
} from "../../../api/pagos-proveedor.service";
import { getReferenciales } from "../../../api/referenciales.service";
import { getProveedor } from "../../../api/proveedores.service";
import { getSucursales } from "../../../api/sucursales.service";
import { getTesCuentas } from "../../../api/tes.service";
import { ProveedorSelector } from "../ProveedoresDesign/ProveedorSelector";
import { ConfirmDialog } from "../../ui/ConfirmDialog";
import { BancoSelect, CotizacionHint, EmptyState, ListToolbar, ScreenGuia, RowActions } from "../../_standards";
import { fmtMoneda } from "../../_standards/enums/monedas";
import { describirOrdenAbierta, finPeriodoPagoActualISO } from "../../_standards/enums";
import { useAuthStore } from "../../../store/AuthStore";
import { fmtFechaCalendario } from "../../../utils/fecha";
import { MonedaInput } from "../../common/MonedaInput";
import { useCotizacionVigente } from "../../../hooks/useCotizacionVigente";
import { aFechaISO, rangoFiltroRapido } from "../../../utils/fecha";

// ── Guía ────────────────────────────────────────────────────────────
const GUIA_PASOS = [
  {
    icon: "lucide:file-text",
    color: "#3b82f6",
    titulo: "1. Seleccioná las cuentas a pagar",
    desc: "Elegí el proveedor y marcá las facturas pendientes que querés incluir en esta orden. Podés agrupar varias facturas en un solo pago.",
  },
  {
    icon: "lucide:credit-card",
    color: "#f59e0b",
    titulo: "2. Definí el medio de pago por línea",
    desc: "Cada línea puede tener un medio de pago distinto (transferencia, cheque, efectivo). Esto determina cómo se registra en Tesorería.",
  },
  {
    icon: "lucide:send",
    color: "#8b5cf6",
    titulo: "3. Enviá a aprobación (si aplica)",
    desc: "Según la configuración de tu empresa, la orden puede requerir aprobación antes de ejecutarse.",
  },
  {
    icon: "lucide:landmark",
    color: "#22c55e",
    titulo: "4. Ejecutar el pago",
    desc: "Al ejecutar, se registra automáticamente el egreso en Tesorería (o el cheque emitido) y se contabiliza la cancelación de la deuda.",
  },
];
const GUIA_NOTAS = [
  {
    icon: "lucide:settings",
    text: "Para que el egreso se acredite al banco correcto, cada cuenta bancaria en Tesorería debe tener vinculada su cuenta contable (Tesorería → Cuentas → editar cuenta → campo \"Cuenta contable\").",
  },
  {
    icon: "lucide:settings",
    text: "Para que los pagos con cheque generen un cheque emitido en Tesorería, configurá la regla \"Pago a proveedor\" para el medio de pago correspondiente (Tesorería → Configuración → Reglas).",
  },
  {
    icon: "lucide:tag",
    text: "Los tipos de gasto pueden vincularse a una cuenta contable específica (Compras → Configuración → Tipos de gasto), de lo contrario se imputa a Gastos Generales.",
  },
];

const parseNumber = (value, fallback = 0) => {
  const n = Number(value);
  return Number.isFinite(n) ? n : fallback;
};

const toArray = (value) => (Array.isArray(value) ? value : value?.data || value?.items || []);

const getMonedaOptionId = (moneda) => moneda?.moneda_id || moneda?.moneda?.id || moneda?.id || "";

const getMonedaCodigo = (moneda) => moneda?.moneda?.codigo || moneda?.codigo || "";

const getMonedaDescripcion = (moneda) => moneda?.moneda?.descripcion || moneda?.descripcion || "";

const normalizeEmpresaMonedaOption = (moneda) => {
  const id = getMonedaOptionId(moneda);
  const codigo = getMonedaCodigo(moneda);
  const descripcion = getMonedaDescripcion(moneda);
  const active = moneda?.active ?? moneda?.activo ?? moneda?.moneda?.active ?? true;

  return {
    ...moneda,
    id,
    moneda_id: id,
    codigo,
    descripcion,
    activo: active,
    moneda: moneda?.moneda || {
      id,
      codigo,
      descripcion,
      simbolo: moneda?.simbolo,
      posicion_simbolo: moneda?.posicion_simbolo,
      decimales_estandar: moneda?.decimales_estandar,
    },
  };
};

const normalizeEmpresaMonedas = (monedas = []) => {
  const byId = new Map();
  for (const moneda of monedas) {
    const normalized = normalizeEmpresaMonedaOption(moneda);
    if (!normalized.id || byId.has(normalized.id)) continue;
    byId.set(normalized.id, normalized);
  }
  return Array.from(byId.values());
};


const getStartOfWeek = (date) => {
  const d = new Date(date);
  const day = d.getDay();
  const diff = day === 0 ? -6 : 1 - day;
  d.setDate(d.getDate() + diff);
  d.setHours(0, 0, 0, 0);
  return d;
};

const formatCurrency = (value, symbol = "Gs.") => {
  const amount = parseNumber(value, 0);
  return `${symbol} ${amount.toLocaleString("es-PY", {
    minimumFractionDigits: 0,
    maximumFractionDigits: 2,
  })}`;
};

const formatDate = (value) => {
  if (!value) return "-";

  if (value instanceof Date) {
    if (Number.isNaN(value.getTime())) return "-";
    return value.toLocaleDateString("es-PY", {
      day: "2-digit",
      month: "2-digit",
      year: "numeric",
    });
  }

  if (typeof value === "string") {
    const match = value.match(/^(\d{4})-(\d{2})-(\d{2})/);
    if (match) return `${match[3]}/${match[2]}/${match[1]}`;
    const parsed = new Date(value);
    if (!Number.isNaN(parsed.getTime())) {
      return parsed.toLocaleDateString("es-PY", {
        day: "2-digit",
        month: "2-digit",
        year: "numeric",
      });
    }
  }

  if (typeof value === "object") {
    if (value?.$date) return formatDate(value.$date);
    if (value?.$d) return formatDate(value.$d);
    if (typeof value?.toISOString === "function") {
      try {
        return formatDate(value.toISOString());
      } catch {
        return "-";
      }
    }
  }

  return "-";
};

const formatDateTime = (value) => {
  if (!value) return "-";

  const parsed = value instanceof Date ? value : new Date(value);
  if (Number.isNaN(parsed.getTime())) return formatDate(value);

  return parsed.toLocaleString("es-PY", {
    day: "2-digit",
    month: "2-digit",
    year: "numeric",
    hour: "2-digit",
    minute: "2-digit",
    hour12: false,
  });
};

const formatCompraComprobante = (compra) => {
  if (!compra) return "S/N";
  const establecimiento = String(compra.establecimiento || "").trim();
  const punto = String(compra.punto_expedicion || "").trim();
  const numero = String(compra.numero_factura || "").trim();

  if (establecimiento && punto && numero) {
    return `${establecimiento.padStart(3, "0")}-${punto.padStart(3, "0")}-${numero.padStart(7, "0")}`;
  }

  return numero || "S/N";
};

const getCuentaDocumentoRef = (cuenta) => {
  const documentoRef = String(cuenta?.documento_ref || "").trim();
  if (documentoRef) return documentoRef;
  return formatCompraComprobante(cuenta?.compra_cab);
};

const getCuentaOrigenTipo = (cuenta) => {
  const normalized = normalizeText(cuenta?.origen_tipo || "");
  if (normalized === "gasto") return "gasto";
  return "compra";
};

const getCuentaOrigenLabel = (cuenta) => (getCuentaOrigenTipo(cuenta) === "gasto" ? "Gasto" : "Compra");

const normalizeText = (value = "") =>
  String(value)
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .toLowerCase();

const normalizeOrdenEstado = (value, anulado = false) => {
  if (anulado) {
    return { key: "ANULADA", label: "Anulada", color: "warning" };
  }

  const raw = String(value || "").toUpperCase();
  if (raw === "PAGADO" || raw === "APLICADO") {
    return { key: "PAGADO", label: "Pagada", color: "success" };
  }
  if (raw === "PENDIENTE_APROBACION") {
    return { key: "PENDIENTE_APROBACION", label: "Pend. aprobación", color: "warning" };
  }
  if (raw === "RECHAZADA") {
    return { key: "RECHAZADA", label: "Rechazada", color: "error" };
  }
  if (raw === "PENDIENTE") {
    return { key: "PENDIENTE", label: "Aprobada", color: "info" };
  }
  if (raw === "BORRADOR") {
    return { key: "BORRADOR", label: "Borrador", color: "default" };
  }

  return { key: raw || "BORRADOR", label: raw || "Borrador", color: "default" };
};

const ORDER_FIELD_INPUT_SX = {
  "& .MuiOutlinedInput-root": {
    minHeight: 42,
    borderRadius: "8px",
    backgroundColor: "rgba(255,255,255,0.03)",
  },
  "& .MuiInputBase-input": {
    fontSize: "0.95rem",
  },
};

const isMedioCheque = (medio) => {
  if (!medio) return false;
  const codigo = Number(medio.codigo);
  const descripcion = normalizeText(medio.descripcion || medio.nombre);
  if (descripcion.includes("cheque")) return true;
  return codigo === 2;
};

const isMedioTarjeta = (medio) => {
  if (!medio) return false;
  const codigo = Number(medio.codigo);
  const descripcion = normalizeText(medio.descripcion || medio.nombre);
  if (descripcion.includes("tarjeta")) return true;
  return codigo === 3 || codigo === 4;
};

const isMedioTransferencia = (medio) => {
  if (!medio) return false;
  const codigo = Number(medio.codigo);
  const descripcion = normalizeText(medio.descripcion || medio.nombre);
  if (descripcion.includes("transferencia")) return true;
  return codigo === 5 || codigo === 7;
};

const isMedioDeposito = (medio) => {
  if (!medio) return false;
  const descripcion = normalizeText(medio.descripcion || medio.nombre);
  return descripcion.includes("deposito") || descripcion.includes("deposito bancario");
};

const getDatosMedioCompleto = (config, medio) => {
  if (!medio) return true;
  if (isMedioCheque(medio)) {
    return !!(
      config.cuenta_bancaria_id &&
      config.numero_cheque?.trim() &&
      config.banco_emisor?.trim() &&
      config.titular_cheque?.trim() &&
      config.fecha_emision_cheque
    );
  }
  if (isMedioTarjeta(medio)) {
    return !!(config.tarjeta_id && String(config.numero_tarjeta || "").length === 4);
  }
  if (isMedioTransferencia(medio) || isMedioDeposito(medio)) {
    return !!config.cuenta_bancaria_id;
  }
  return true;
};

const getDatosMedioResumen = (config, medio, cuentasBancarias, tarjetas) => {
  if (isMedioCheque(medio)) {
    if (!config.numero_cheque) return null;
    return `Cheque N°${config.numero_cheque}${config.banco_emisor ? ` — ${config.banco_emisor}` : ""}`;
  }
  if (isMedioTarjeta(medio)) {
    const t = tarjetas.find((x) => x.id === config.tarjeta_id);
    if (!t) return null;
    return `${t.descripcion}${config.numero_tarjeta ? ` ****${config.numero_tarjeta}` : ""}`;
  }
  if (isMedioTransferencia(medio) || isMedioDeposito(medio)) {
    const cb = cuentasBancarias.find((c) => c.id === config.cuenta_bancaria_id);
    return cb ? cb.nombre : null;
  }
  return null;
};

const emptyOrderForm = {
  sucursal_id: "",
  proveedor_id: "",
  sesion_caja_id: "",
  moneda_id: "",
  cotizacion: 1,
  fecha_pago: aFechaISO(new Date()),
  medio_pago_id: "",
  referencia: "",
  observaciones: "",
};

export function ComprasPagosTab({
  sucursalesProp = null,
  monedasProp = null,
  mediosPagoProp = null,
}) {
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down("sm"));

  const [loadingList, setLoadingList] = useState(false);
  const [loadingDashboard, setLoadingDashboard] = useState(false);
  const [loadingPendientes, setLoadingPendientes] = useState(false);
  const [saving, setSaving] = useState(false);

  const [pagos, setPagos] = useState([]);
  const [totalPagos, setTotalPagos] = useState(0);
  const [dashboard, setDashboard] = useState({
    total: 0,
    pagadas: 0,
    anuladas: 0,
    monto_total: 0,
  });
  const [configCompras, setConfigCompras] = useState({
    aplicar_pago_al_guardar: true,
    requiere_aprobacion: false,
    permite_pago_sin_aprobacion: true,
    usar_workflow: false,
    workflow_obligatorio: false,
  });

  const [page, setPage] = useState(1);
  const [limit, setLimit] = useState(20);
  const [estadoFilter, setEstadoFilter] = useState("");
  const [searchText, setSearchText] = useState("");
  // El chip arranca en "Esta semana": las fechas se inicializan con él, porque
  // marcarlo sin setear el rango dejaba la lista mostrando todo.
  const [fechaDesde, setFechaDesde] = useState(() => rangoFiltroRapido("semana").desde);
  const [fechaHasta, setFechaHasta] = useState(() => rangoFiltroRapido("semana").hasta);
  const [filtroRapido, setFiltroRapido] = useState("semana");
  const [showFilters, setShowFilters] = useState(false);

  const [showForm, setShowForm] = useState(false);


  const [orderForm, setOrderForm] = useState(emptyOrderForm);
  const [selectedProveedor, setSelectedProveedor] = useState(null);
  // Plan de pagos semanal → «Generar orden»: llega ?proveedor=&cuotas= y el
  // formulario se abre con ese proveedor y solo esas cuotas marcadas.
  const [searchParams, setSearchParams] = useSearchParams();
  const cuotasPrefillRef = useRef(null);
  // Con el submódulo Plan de pagos, la orden marca por defecto solo lo programado hasta el
  // fin del período en curso; sin él, se comporta como siempre (todas las pendientes).
  const planPagosActivo = useAuthStore((st) => st.hasPermission("COMPRAS", "CMP_PP_PLAN_PAGOS_VER"));
  const [cuentasPendientes, setCuentasPendientes] = useState([]);
  const [selectedCuentaIds, setSelectedCuentaIds] = useState([]);
  const [cuentasPagoConfig, setCuentasPagoConfig] = useState({});
  const [anularConfirmOpen, setAnularConfirmOpen] = useState(false);
  const [pendingAnularOrden, setPendingAnularOrden] = useState(null);
  const [anulandoOrden, setAnulandoOrden] = useState(false);
  const [saveConfirmOpen, setSaveConfirmOpen] = useState(false);
  const [pendingCreateOrder, setPendingCreateOrder] = useState(null);
  // Mensaje del warning de tesoreria — string vacío = cerrado.
  const [tesoreriaWarningOpen, setTesoreriaWarningOpen] = useState("");
  const navigate = useNavigate();
  const [detalleOpen, setDetalleOpen] = useState(false);
  const [detalleLoading, setDetalleLoading] = useState(false);
  const [detalleOrden, setDetalleOrden] = useState(null);
  const [pdfLoadingId, setPdfLoadingId] = useState(null);
  const [pdfPreview, setPdfPreview] = useState(null);
  const [executingOrderId, setExecutingOrderId] = useState(null);
  const [workflowActionId, setWorkflowActionId] = useState(null);
  const [workflowConfirmOpen, setWorkflowConfirmOpen] = useState(false);
  const [workflowConfirmType, setWorkflowConfirmType] = useState(null);
  const [pendingWorkflowOrden, setPendingWorkflowOrden] = useState(null);

  const [sucursales, setSucursales] = useState([]);
  const [monedas, setMonedas] = useState([]);
  const [mediosPago, setMediosPago] = useState([]);
  const [tarjetas, setTarjetas] = useState([]);
  const [cuentasBancarias, setCuentasBancarias] = useState([]);
  const [datosMedioDialog, setDatosMedioDialog] = useState({ open: false, cuentaId: null });

  const filtrosActivos = useMemo(
    () => [searchText, estadoFilter, fechaDesde, fechaHasta].filter(Boolean).length,
    [searchText, estadoFilter, fechaDesde, fechaHasta],
  );

  const totalPages = useMemo(
    () => Math.max(1, Math.ceil(parseNumber(totalPagos, 0) / parseNumber(limit, 20))),
    [totalPagos, limit],
  );

  // Totales de OP visibles agrupados por moneda (evita mezclar PYG con USD en el KPI).
  const montoAplicadoPorMoneda = useMemo(() => {
    const acc = {};
    for (const p of pagos) {
      const code = p?.moneda?.codigo || "PYG";
      acc[code] = (acc[code] || 0) + parseNumber(p?.monto_total, 0);
    }
    return acc;
  }, [pagos]);

  const totalSeleccionado = useMemo(() => {
    const selected = new Set(selectedCuentaIds);
    const permitePagoParcial = Boolean(configCompras.permitir_pago_parcial);
    return cuentasPendientes
      .filter((c) => selected.has(c.id))
      .reduce((acc, c) => {
        const saldo = parseNumber(c.saldo_pendiente, 0);
        if (!permitePagoParcial) return acc + saldo;
        const montoConfigurado = parseNumber(cuentasPagoConfig[c.id]?.monto, saldo);
        const montoValido = Math.max(0, Math.min(saldo, montoConfigurado));
        return acc + montoValido;
      }, 0);
  }, [cuentasPendientes, selectedCuentaIds, cuentasPagoConfig, configCompras.permitir_pago_parcial]);

  const cuentasById = useMemo(() => {
    const map = new Map();
    cuentasPendientes.forEach((cuenta) => {
      map.set(cuenta.id, cuenta);
    });
    return map;
  }, [cuentasPendientes]);
  const cuentasLibres = useMemo(() => cuentasPendientes.filter((c) => !c.orden_abierta), [cuentasPendientes]);

  const initCuentaPagoConfig = useCallback(
    () => ({
      medio_pago_id: orderForm.medio_pago_id || mediosPago?.[0]?.id || "",
      referencia: orderForm.referencia || "",
      // cheque
      numero_cheque: "",
      banco_emisor: "",
      titular_cheque: "",
      fecha_emision_cheque: aFechaISO(new Date()),
      fecha_vencimiento_cheque: "",
      // transferencia / depósito
      cuenta_bancaria_id: "",
      numero_operacion: "",
      // tarjeta
      tarjeta_id: "",
      numero_tarjeta: "",
      monto: "",
    }),
    [orderForm.medio_pago_id, orderForm.referencia, mediosPago],
  );

  useEffect(
    () => () => {
      if (pdfPreview?.url) {
        window.URL.revokeObjectURL(pdfPreview.url);
      }
    },
    [pdfPreview],
  );

  const updateCuentaPagoConfig = (cuentaId, field, value) => {
    setCuentasPagoConfig((prev) => {
      const current = {
        ...(prev[cuentaId] || initCuentaPagoConfig(cuentaId)),
        [field]: value,
      };

      if (field === "medio_pago_id") {
        const medio = mediosPago.find((m) => m.id === value);
        const cheque = isMedioCheque(medio);
        const tarjeta = isMedioTarjeta(medio);
        const transferencia = isMedioTransferencia(medio);
        const deposito = isMedioDeposito(medio);

        if (!cheque) {
          current.numero_cheque = "";
          current.banco_emisor = "";
          current.titular_cheque = "";
          current.fecha_emision_cheque = aFechaISO(new Date());
          current.fecha_vencimiento_cheque = "";
        }
        if (!tarjeta) {
          current.tarjeta_id = "";
          current.numero_tarjeta = "";
        }
        // cuenta_bancaria_id se usa para cheque (cartera), transferencia y depósito
        if (!cheque && !transferencia && !deposito) {
          current.cuenta_bancaria_id = "";
        }
        // numero_operacion: para cheque = N° Cuenta del cheque; para transferencia = nro. op.
        if (!cheque && !transferencia) {
          current.numero_operacion = "";
        }
      }

      return {
        ...prev,
        [cuentaId]: current,
      };
    });

    // Abrir el dialog automáticamente cuando se elige un medio que requiere datos.
    if (field === "medio_pago_id") {
      const medio = mediosPago.find((m) => m.id === value);
      if (
        isMedioCheque(medio) ||
        isMedioTarjeta(medio) ||
        isMedioTransferencia(medio) ||
        isMedioDeposito(medio)
      ) {
        setDatosMedioDialog({ open: true, cuentaId });
      }
    }
  };

  const loadLookups = useCallback(async () => {
    // Cuentas bancarias: siempre se cargan. Los bancos los trae BancoSelect.
    try {
      const cuentasResp = await getTesCuentas({ activo: true, limit: 200 });
      setCuentasBancarias(
        Array.isArray(cuentasResp?.data) ? cuentasResp.data
        : Array.isArray(cuentasResp) ? cuentasResp
        : []
      );
    } catch {
      setCuentasBancarias([]);
    }

    if (Array.isArray(sucursalesProp) && Array.isArray(monedasProp) && Array.isArray(mediosPagoProp)) {
      setSucursales(sucursalesProp);
      setMonedas(normalizeEmpresaMonedas(monedasProp));
      setMediosPago(mediosPagoProp);
      setTarjetas([]);
      return;
    }

    try {
      const [empresaMonedasResp, mediosResp, sucursalesResp, refsResp] = await Promise.all([
        getEmpresaMonedas(),
        getMediosPagoActivos(),
        getSucursales(1, 200),
        getReferenciales(),
      ]);

      setMonedas(normalizeEmpresaMonedas(toArray(empresaMonedasResp)));
      setMediosPago(Array.isArray(mediosResp?.data) ? mediosResp.data : Array.isArray(mediosResp) ? mediosResp : []);
      setSucursales(toArray(sucursalesResp));
      setTarjetas(Array.isArray(refsResp?.tarjeta) ? refsResp.tarjeta : []);
    } catch (error) {
      console.error(error);
      toast.error("No se pudieron cargar datos auxiliares de pagos");
    }
  }, [sucursalesProp, monedasProp, mediosPagoProp]);

  const loadPagos = useCallback(async () => {
    try {
      setLoadingList(true);
      const resp = await getPagosProveedor({
        page,
        limit,
        estado: estadoFilter || undefined,
        fecha_desde: fechaDesde || undefined,
        fecha_hasta: fechaHasta || undefined,
        busqueda: searchText || undefined,
      });
      setPagos(resp?.items || []);
      setTotalPagos(resp?.total || 0);
    } catch (error) {
      console.error(error);
      toast.error("No se pudo cargar el listado de pagos");
    } finally {
      setLoadingList(false);
    }
  }, [page, limit, estadoFilter, fechaDesde, fechaHasta, searchText]);

  const loadDashboard = useCallback(async () => {
    try {
      setLoadingDashboard(true);
      const resp = await getPagosProveedorDashboard({
        fecha_desde: fechaDesde || undefined,
        fecha_hasta: fechaHasta || undefined,
      });
      setDashboard({
        total: parseNumber(resp?.total, 0),
        pagadas: parseNumber(resp?.pagadas ?? resp?.aplicadas, 0),
        anuladas: parseNumber(resp?.anuladas, 0),
        monto_total: parseNumber(resp?.monto_total, 0),
      });
    } catch (error) {
      console.error(error);
      setDashboard({ total: 0, pagadas: 0, anuladas: 0, monto_total: 0 });
    } finally {
      setLoadingDashboard(false);
    }
  }, [fechaDesde, fechaHasta]);

  const loadConfigCompras = useCallback(async () => {
    try {
      const config = await getConfigCompras();
      setConfigCompras((prev) => ({
        ...prev,
        ...(config || {}),
      }));
    } catch (error) {
      console.error(error);
    }
  }, []);

  useEffect(() => {
    loadLookups();
  }, [loadLookups]);

  useEffect(() => {
    loadConfigCompras();
  }, [loadConfigCompras]);

  useEffect(() => {
    const today = new Date();
    const start = getStartOfWeek(today);
    setFechaDesde(aFechaISO(start));
    setFechaHasta(aFechaISO(today));
  }, []);

  useEffect(() => {
    loadPagos();
    loadDashboard();
  }, [loadPagos, loadDashboard]);

  useEffect(() => {
    if (!showForm) return;
    if (!selectedProveedor?.id) {
      setCuentasPendientes([]);
      setSelectedCuentaIds([]);
      return;
    }

    const run = async () => {
      try {
        setLoadingPendientes(true);
        const resp = await getCuentasPendientesProveedor(selectedProveedor.id);
        const items = resp?.items || [];
        setCuentasPendientes(items);
        // La preselección vale solo para el proveedor que vino del plan; no se consume
        // acá porque el efecto puede correr dos veces (StrictMode) y la perderíamos.
        const prefill = cuotasPrefillRef.current?.proveedorId === selectedProveedor.id ? cuotasPrefillRef.current.ids : null;
        // Las que ya están en otra orden sin ejecutar no se pueden marcar (el backend lo rechaza).
        const libres = items.filter((item) => !item.orden_abierta);
        const finPeriodo = finPeriodoPagoActualISO(configCompras);
        const elegidas = prefill
          ? libres.filter((item) => prefill.includes(item.id))
          : planPagosActivo
            ? libres.filter((item) => item.fecha_pago_programada && String(item.fecha_pago_programada).slice(0, 10) <= finPeriodo)
            : libres;
        if (prefill && elegidas.length < prefill.length) {
          toast.info("Algunas cuotas del plan ya no están pendientes o ya están en otra orden de pago, y no se incluyeron");
        }
        setSelectedCuentaIds(elegidas.map((item) => item.id));
      } catch (error) {
        console.error(error);
        setCuentasPendientes([]);
        setSelectedCuentaIds([]);
        toast.error("No se pudieron cargar las cuentas pendientes del proveedor");
      } finally {
        setLoadingPendientes(false);
      }
    };

    run();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [showForm, selectedProveedor]);

  useEffect(() => {
    if (!showForm) return;

    const monedaDefault = monedas.find((m) => m.es_principal && m.activo !== false) || monedas?.[0];

    setOrderForm((prev) => ({
      ...prev,
      sucursal_id: prev.sucursal_id || sucursales?.[0]?.id || "",
      moneda_id: prev.moneda_id || monedaDefault?.id || "",
      medio_pago_id: prev.medio_pago_id || mediosPago?.[0]?.id || "",
    }));
  }, [showForm, sucursales, monedas, mediosPago]);

  useEffect(() => {
    if (!showForm || selectedCuentaIds.length === 0) return;
    setCuentasPagoConfig((prev) => {
      const next = { ...prev };
      let changed = false;
      selectedCuentaIds.forEach((cuentaId) => {
        const cuenta = cuentasById.get(cuentaId);
        const saldo = parseNumber(cuenta?.saldo_pendiente, 0);
        if (!next[cuentaId]) {
          next[cuentaId] = {
            ...initCuentaPagoConfig(cuentaId),
            monto: saldo,
          };
          changed = true;
          return;
        }
        if (next[cuentaId].monto === "" || next[cuentaId].monto === undefined || next[cuentaId].monto === null) {
          next[cuentaId] = {
            ...next[cuentaId],
            monto: saldo,
          };
          changed = true;
        }
      });
      return changed ? next : prev;
    });
  }, [showForm, selectedCuentaIds, initCuentaPagoConfig, cuentasById]);

  const aplicarFiltroRapido = (tipo) => {
    const { desde, hasta } = rangoFiltroRapido(tipo);
    setFiltroRapido(tipo);
    setPage(1);
    setFechaDesde(desde);
    setFechaHasta(hasta);
  };

  const limpiarFiltros = () => {
    setSearchText("");
    setEstadoFilter("");
    setFechaDesde("");
    setFechaHasta("");
    setFiltroRapido("");
    setPage(1);
  };

  const openPdfFromBlob = (blob, filename = "orden-pago.pdf") => {
    if (!blob) return;
    const url = window.URL.createObjectURL(blob);
    setPdfPreview((prev) => {
      if (prev?.url) {
        window.URL.revokeObjectURL(prev.url);
      }
      return { url, filename };
    });
  };

  const closePdfPreview = () => {
    setPdfPreview((prev) => {
      if (prev?.url) {
        window.URL.revokeObjectURL(prev.url);
      }
      return null;
    });
  };

  const handleDownloadPdfPreview = () => {
    if (!pdfPreview?.url) return;
    const link = document.createElement("a");
    link.href = pdfPreview.url;
    link.download = pdfPreview.filename || "orden-pago.pdf";
    link.click();
  };

  const handleViewPdf = async (orden) => {
    const id = orden?.id;
    if (!id) return;
    try {
      setPdfLoadingId(id);
      const blob = await getOrdenPagoProveedorPdf(id);
      openPdfFromBlob(blob, `orden-pago-${orden?.numero_orden_pago || "sin-numero"}.pdf`);
    } catch (error) {
      console.error(error);
      toast.error("No se pudo generar el PDF de la orden");
    } finally {
      setPdfLoadingId(null);
    }
  };

  const handleViewDetails = async (id) => {
    if (!id) return;
    try {
      setDetalleLoading(true);
      setDetalleOpen(true);
      const data = await getPagoProveedorById(id);
      setDetalleOrden(data || null);
    } catch (error) {
      console.error(error);
      setDetalleOpen(false);
      toast.error(error?.response?.data?.message || "No se pudo cargar el detalle de la orden");
    } finally {
      setDetalleLoading(false);
    }
  };

  const closeDetalle = () => {
    if (detalleLoading) return;
    setDetalleOpen(false);
    setDetalleOrden(null);
  };

  const requestWorkflowConfirm = (orden, type) => {
    if (!orden?.id) return;
    setPendingWorkflowOrden(orden);
    setWorkflowConfirmType(type);
    setWorkflowConfirmOpen(true);
  };

  const closeWorkflowConfirm = () => {
    if (!workflowConfirmOpen) return;
    setWorkflowConfirmOpen(false);
    setWorkflowConfirmType(null);
    setPendingWorkflowOrden(null);
  };

  const handleConfirmWorkflowAction = async () => {
    const orden = pendingWorkflowOrden;
    const type = workflowConfirmType;
    closeWorkflowConfirm();
    if (!orden?.id || !type) return;
    if (type === "aprobar") {
      await handleAprobarOrden(orden);
      return;
    }
    if (type === "ejecutar") {
      await handleEjecutarOrden(orden);
    }
  };

  const requestAnularOrden = (orden) => {
    if (!orden?.id) return;
    setPendingAnularOrden(orden);
    setAnularConfirmOpen(true);
  };

  const closeAnularConfirm = () => {
    if (anulandoOrden) return;
    setAnularConfirmOpen(false);
    setPendingAnularOrden(null);
  };

  const handleConfirmAnularOrden = async () => {
    if (!pendingAnularOrden?.id) return;
    const loadingToastId = toast.loading("Anulando orden de pago...");
    try {
      setAnulandoOrden(true);
      const response = await anularOrdenPagoProveedor(pendingAnularOrden.id, "Anulación manual");
      toast.dismiss(loadingToastId);
      toast.success(response?.message || "Orden anulada correctamente");
      await Promise.all([loadPagos(), loadDashboard()]);
      setAnularConfirmOpen(false);
      setPendingAnularOrden(null);
    } catch (error) {
      toast.dismiss(loadingToastId);
      console.error(error);
      const message = error?.response?.data?.message || "No se pudo anular la orden";
      if (error?.response?.status === 400) toast.warning(message);
      else toast.error(message);
    } finally {
      setAnulandoOrden(false);
    }
  };

  const resetOrderForm = () => {
    const monedaDefault = monedas.find((m) => m.es_principal && m.activo !== false) || monedas?.[0];

    setOrderForm({
      ...emptyOrderForm,
      sucursal_id: sucursales?.[0]?.id || "",
      moneda_id: monedaDefault?.id || "",
      medio_pago_id: mediosPago?.[0]?.id || "",
    });
    setSelectedProveedor(null);
    setCuentasPendientes([]);
    setSelectedCuentaIds([]);
    setCuentasPagoConfig({});
    cuotasPrefillRef.current = null;
  };

  const handleOpenForm = () => {
    resetOrderForm();
    setShowForm(true);
  };

  useEffect(() => {
    const proveedorId = searchParams.get("proveedor");
    if (!proveedorId) return;
    const cuotas = (searchParams.get("cuotas") || "").split(",").filter(Boolean);
    const fechaPago = /^\d{4}-\d{2}-\d{2}$/.test(searchParams.get("fecha") || "") ? searchParams.get("fecha") : null;
    const limpio = new URLSearchParams(searchParams);
    limpio.delete("proveedor");
    limpio.delete("cuotas");
    limpio.delete("fecha");
    setSearchParams(limpio, { replace: true });
    getProveedor(proveedorId)
      .then((resp) => {
        const proveedor = resp?.data ?? resp; // el endpoint responde { message, data }
        resetOrderForm();
        cuotasPrefillRef.current = cuotas.length ? { proveedorId: proveedor?.id, ids: cuotas } : null;
        setSelectedProveedor(proveedor);
        // Desde el plan, la fecha de pago es la del período elegido.
        setOrderForm((prev) => ({ ...prev, proveedor_id: proveedor?.id || "", ...(fechaPago ? { fecha_pago: fechaPago } : {}) }));
        setShowForm(true);
      })
      .catch(() => toast.error("No se pudo cargar el proveedor del plan de pagos"));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [searchParams]);

  const handleCloseForm = () => {
    resetOrderForm();
    setSaveConfirmOpen(false);
    setPendingCreateOrder(null);
    setShowForm(false);
  };

  const toggleCuenta = (cuentaId) => {
    const cuenta = cuentasById.get(cuentaId);
    if (cuenta?.orden_abierta) return;
    const saldo = parseNumber(cuenta?.saldo_pendiente, 0);
    const cuentaMonedaId = cuenta?.moneda?.id || cuenta?.moneda_id || null;
    setSelectedCuentaIds((prev) => {
      const exists = prev.includes(cuentaId);
      if (exists) return prev.filter((id) => id !== cuentaId);
      // Al agregar: bloquear mezcla de monedas para no cerrar CxP USD con Gs.
      if (prev.length > 0 && cuentaMonedaId) {
        const anyOther = prev
          .map((id) => cuentasById.get(id))
          .find((c) => (c?.moneda?.id || c?.moneda_id) && (c?.moneda?.id || c?.moneda_id) !== cuentaMonedaId);
        if (anyOther) {
          toast.warning(
            "No se pueden pagar cuentas en distinta moneda en la misma OP. Emití una OP por moneda.",
          );
          return prev;
        }
      }
      return [...prev, cuentaId];
    });
    setCuentasPagoConfig((prev) => ({
      ...prev,
      [cuentaId]:
        prev[cuentaId] || {
          ...initCuentaPagoConfig(cuentaId),
          monto: saldo,
        },
    }));
  };

  // FASE 3 — Detección de inconsistencia de monedas en la selección de CxPs.
  // La OP debe pagar cuentas de una sola moneda; si el usuario mezcló, mostramos
  // banner + bloqueamos el submit para no cerrar CxP USD con Gs.
  const monedasEnSeleccion = useMemo(() => {
    const codigos = new Set();
    for (const id of selectedCuentaIds) {
      const c = cuentasById.get(id);
      const code = c?.moneda?.codigo || c?.moneda_id || null;
      if (code) codigos.add(code);
    }
    return Array.from(codigos);
  }, [selectedCuentaIds, cuentasById]);
  const hayMonedasMezcladas = monedasEnSeleccion.length > 1;
  const monedaFormCodigo = useMemo(
    () => monedas.find((m) => m.id === orderForm.moneda_id)?.codigo || null,
    [monedas, orderForm.moneda_id],
  );
  const monedaSeleccionCodigo = useMemo(() => {
    if (selectedCuentaIds.length === 0) return null;
    const c = cuentasById.get(selectedCuentaIds[0]);
    return c?.moneda?.codigo || null;
  }, [selectedCuentaIds, cuentasById]);
  const monedaFormDesalineada =
    !hayMonedasMezcladas &&
    monedaSeleccionCodigo &&
    monedaFormCodigo &&
    monedaFormCodigo !== monedaSeleccionCodigo;

  // FASE 3 — cotización vigente (contabilidad → facturación → fallback).
  const [cotizacionTocada, setCotizacionTocada] = useState(false);
  const monedaSeleccionadaCodigo = useMemo(
    () => monedas.find((m) => m.id === orderForm.moneda_id)?.codigo || null,
    [monedas, orderForm.moneda_id],
  );
  const { data: cotizacionVigente } = useCotizacionVigente(
    monedaSeleccionadaCodigo,
    orderForm.fecha_pago,
  );
  useEffect(() => {
    if (!showForm) return;
    if (cotizacionTocada) return;
    if (!cotizacionVigente?.tasa) return;
    const actual = Number(orderForm.cotizacion) || 0;
    if (Math.abs(actual - cotizacionVigente.tasa) < 1e-6) return;
    setOrderForm((prev) => ({ ...prev, cotizacion: cotizacionVigente.tasa }));
  }, [cotizacionVigente?.tasa, showForm, cotizacionTocada, orderForm.cotizacion]);
  // Al cambiar de moneda, resetear el flag para que la nueva cotización se auto-cargue.
  useEffect(() => {
    setCotizacionTocada(false);
  }, [orderForm.moneda_id]);

  // Auto-alinear la moneda de la OP con la moneda de las CxPs seleccionadas.
  // Cualquier cambio en la selección re-sincroniza (agregar/quitar/toggle all).
  useEffect(() => {
    if (!showForm || selectedCuentaIds.length === 0) return;
    const monedasSel = new Set(
      selectedCuentaIds
        .map((id) => {
          const c = cuentasById.get(id);
          return c?.moneda?.id || c?.moneda_id || null;
        })
        .filter(Boolean),
    );
    if (monedasSel.size === 1) {
      const monedaCxp = Array.from(monedasSel)[0];
      if (monedaCxp && orderForm.moneda_id !== monedaCxp) {
        setOrderForm((f) => ({ ...f, moneda_id: monedaCxp }));
      }
    }
  }, [selectedCuentaIds, cuentasById, showForm, orderForm.moneda_id]);

  const toggleAllCuentas = () => {
    if (cuentasLibres.length > 0 && selectedCuentaIds.length === cuentasLibres.length) {
      setSelectedCuentaIds([]);
      return;
    }
    // Solo seleccionar CxP en la misma moneda que la primera pendiente (y no las que
    // ya están en otra orden de pago sin ejecutar).
    const primeraMoneda =
      cuentasLibres[0]?.moneda?.id || cuentasLibres[0]?.moneda_id || null;
    const mismasMoneda = cuentasLibres.filter(
      (c) => (c?.moneda?.id || c?.moneda_id || null) === primeraMoneda,
    );
    if (mismasMoneda.length < cuentasLibres.length) {
      toast.warning(
        "Se seleccionaron sólo las cuentas en la moneda mayoritaria. Para el resto emití OPs separadas.",
      );
    }
    const allIds = mismasMoneda.map((cuenta) => cuenta.id);
    if (primeraMoneda && orderForm.moneda_id !== primeraMoneda) {
      setOrderForm((f) => ({ ...f, moneda_id: primeraMoneda }));
    }
    setSelectedCuentaIds(allIds);
    setCuentasPagoConfig((prev) => {
      const next = { ...prev };
      allIds.forEach((cuentaId) => {
        const saldo = parseNumber(cuentasById.get(cuentaId)?.saldo_pendiente, 0);
        if (!next[cuentaId]) {
          next[cuentaId] = {
            ...initCuentaPagoConfig(cuentaId),
            monto: saldo,
          };
        }
      });
      return next;
    });
  };

  const buildCreateOrderPayload = () => {
    if (!selectedProveedor?.id || !orderForm.proveedor_id) {
      toast.error("Seleccioná un proveedor");
      return null;
    }

    if (!orderForm.sucursal_id) {
      toast.error("Seleccioná una sucursal");
      return null;
    }

    if (selectedCuentaIds.length === 0) {
      toast.error("Seleccioná al menos una cuenta por pagar");
      return null;
    }

    const permitePagoParcial = Boolean(configCompras.permitir_pago_parcial);
    const detalles = selectedCuentaIds
      .map((cuentaId) => {
        const cuenta = cuentasById.get(cuentaId);
        if (!cuenta) return null;
        const saldo = parseNumber(cuenta.saldo_pendiente, 0);
        const configCuenta = cuentasPagoConfig[cuentaId] || {};
        const montoInput = parseNumber(configCuenta.monto, saldo);
        const monto = permitePagoParcial ? montoInput : saldo;
        if (monto <= 0) {
          toast.error(`Ingresá un monto mayor a 0 para el documento ${getCuentaDocumentoRef(cuenta)}`);
          return null;
        }
        if (monto > saldo) {
          toast.error(`El monto no puede superar el saldo pendiente en ${getCuentaDocumentoRef(cuenta)}`);
          return null;
        }
        if (!permitePagoParcial && Math.abs(monto - saldo) > 0.0001) {
          toast.error(
            `La configuración actual exige pago exacto al saldo pendiente en ${getCuentaDocumentoRef(cuenta)}`,
          );
          return null;
        }
        const medioPagoId = configCuenta.medio_pago_id || orderForm.medio_pago_id || "";
        const medio = mediosPago.find((m) => m.id === medioPagoId);
        const metaObservaciones = [];

        if (isMedioCheque(medio)) {
          if (!configCuenta.cuenta_bancaria_id) {
            toast.error(`Seleccioná la cuenta tesorería para el cheque en ${getCuentaDocumentoRef(cuenta)}`);
            return null;
          }
          if (!configCuenta.numero_cheque?.trim()) {
            toast.error(`Ingresá número de cheque para el documento ${getCuentaDocumentoRef(cuenta)}`);
            return null;
          }
          if (!configCuenta.banco_emisor?.trim()) {
            toast.error(`Ingresá banco emisor para el cheque en ${getCuentaDocumentoRef(cuenta)}`);
            return null;
          }
          if (!configCuenta.titular_cheque?.trim()) {
            toast.error(`Ingresá el titular del cheque en ${getCuentaDocumentoRef(cuenta)}`);
            return null;
          }
          if (!configCuenta.fecha_emision_cheque) {
            toast.error(`Ingresá la fecha de emisión del cheque en ${getCuentaDocumentoRef(cuenta)}`);
            return null;
          }
          metaObservaciones.push(`Cheque N° ${configCuenta.numero_cheque.trim()}`);
          if (configCuenta.banco_emisor) metaObservaciones.push(`Banco: ${configCuenta.banco_emisor}`);
        }

        if (isMedioTarjeta(medio)) {
          if (!configCuenta.tarjeta_id) {
            toast.error(`Seleccioná tarjeta para el documento ${getCuentaDocumentoRef(cuenta)}`);
            return null;
          }
          const tarjeta = tarjetas.find((t) => t.id === configCuenta.tarjeta_id);
          if (!configCuenta.numero_tarjeta || String(configCuenta.numero_tarjeta).length !== 4) {
            toast.error(
              `Ingresá los últimos 4 dígitos de la tarjeta para el documento ${getCuentaDocumentoRef(cuenta)}`,
            );
            return null;
          }
          metaObservaciones.push(
            `Tarjeta ${tarjeta?.descripcion || "S/T"} ****${String(configCuenta.numero_tarjeta)}`,
          );
        }

        if (isMedioTransferencia(medio) && !configCuenta.cuenta_bancaria_id) {
          toast.error(`Seleccioná la cuenta bancaria de origen para el documento ${getCuentaDocumentoRef(cuenta)}`);
          return null;
        }

        if (isMedioDeposito(medio) && !configCuenta.cuenta_bancaria_id) {
          toast.error(`Seleccioná la cuenta bancaria de destino para el documento ${getCuentaDocumentoRef(cuenta)}`);
          return null;
        }

        return {
          cuenta_pagar_id: cuenta.id,
          medio_pago_id: medioPagoId,
          monto,
          monto_moneda: monto,
          cotizacion: parseNumber(orderForm.cotizacion, 1),
          referencia: configCuenta.referencia || orderForm.referencia || undefined,
          observaciones:
            metaObservaciones.length > 0
              ? metaObservaciones.join(" | ")
              : undefined,
          // datos específicos por medio
          numero_cheque: isMedioCheque(medio) ? configCuenta.numero_cheque?.trim() || undefined : undefined,
          banco_emisor: isMedioCheque(medio) ? configCuenta.banco_emisor?.trim() || undefined : undefined,
          titular_cheque: isMedioCheque(medio) ? configCuenta.titular_cheque?.trim() || undefined : undefined,
          fecha_emision_cheque: isMedioCheque(medio) ? configCuenta.fecha_emision_cheque || undefined : undefined,
          fecha_vencimiento_cheque: isMedioCheque(medio) ? configCuenta.fecha_vencimiento_cheque || undefined : undefined,
          cuenta_bancaria_id:
            (isMedioCheque(medio) || isMedioTransferencia(medio) || isMedioDeposito(medio))
              ? configCuenta.cuenta_bancaria_id || undefined
              : undefined,
          // cheque: N° Cuenta del cheque (cuenta_bancaria_origen en tes_cheques)
          // transferencia: nro. operación/referencia bancaria
          numero_operacion:
            (isMedioCheque(medio) || isMedioTransferencia(medio))
              ? configCuenta.numero_operacion?.trim() || undefined
              : undefined,
        };
      })
      .filter(Boolean);

    const detalleSinMedio = detalles.find((d) => !d.medio_pago_id);
    if (detalleSinMedio) {
      const cuenta = cuentasById.get(detalleSinMedio.cuenta_pagar_id);
      toast.error(`Seleccioná medio de pago para el documento ${getCuentaDocumentoRef(cuenta)}`);
      return null;
    }

    if (detalles.length !== selectedCuentaIds.length) {
      return null;
    }

    if (detalles.length === 0) {
      toast.error("No se pudieron preparar los detalles de la orden");
      return null;
    }

    const payload = {
      sucursal_id: orderForm.sucursal_id,
      proveedor_id: orderForm.proveedor_id,
      sesion_caja_id: orderForm.sesion_caja_id || undefined,
      moneda_id: orderForm.moneda_id || undefined,
      cotizacion: parseNumber(orderForm.cotizacion, 1),
      fecha_pago: orderForm.fecha_pago || undefined,
      referencia: orderForm.referencia || undefined,
      observaciones: orderForm.observaciones || undefined,
      detalles,
    };

    const monedaSel = monedas.find((m) => m.id === orderForm.moneda_id);
    return {
      payload,
      total: parseNumber(totalSeleccionado, 0),
      cantidadCuentas: detalles.length,
      proveedorNombre: selectedProveedor?.personas?.razon_social || "Sin nombre",
      cantidadMedios: new Set(detalles.map((d) => d.medio_pago_id)).size,
      monedaCodigo: monedaSel?.codigo || "PYG",
      monedaSimbolo: monedaSel?.simbolo || "Gs.",
    };
  };

  const handleRequestSubmit = () => {
    const prepared = buildCreateOrderPayload();
    if (!prepared) return;
    setPendingCreateOrder(prepared);
    setSaveConfirmOpen(true);
  };

  const closeSaveConfirm = () => {
    if (saving) return;
    setSaveConfirmOpen(false);
    setPendingCreateOrder(null);
  };

  const handleConfirmSubmit = async () => {
    if (!pendingCreateOrder?.payload) return;
    const aplicaAlGuardar = Boolean(configCompras.aplicar_pago_al_guardar) && !requiereAprobacionOrden;
    const loadingToastId = toast.loading(aplicaAlGuardar ? "Guardando y ejecutando orden..." : "Guardando orden borrador...");
    try {
      setSaving(true);
      const created = await createOrdenPagoProveedor(pendingCreateOrder.payload);
      toast.dismiss(loadingToastId);
      toast.success(
        created?.message ||
          (aplicaAlGuardar ? "Pago aplicado correctamente" : "Orden de pago borrador registrada"),
      );
      if (created?.tesoreria_warning) {
        setTesoreriaWarningOpen(created.tesoreria_warning);
      }

      if (created?.id) {
        try {
          const blob = await getOrdenPagoProveedorPdf(created.id);
          openPdfFromBlob(blob, `orden-pago-${created.numero_orden_pago || "sin-numero"}.pdf`);
        } catch (error) {
          console.error(error);
          toast.warning("La orden se guardó, pero no se pudo abrir el PDF automáticamente");
        }
      }

      await Promise.all([loadPagos(), loadDashboard()]);
      setSaveConfirmOpen(false);
      setPendingCreateOrder(null);
      handleCloseForm();
    } catch (error) {
      toast.dismiss(loadingToastId);
      console.error(error);
      const message = error?.response?.data?.message || "No se pudo registrar la orden";
      if (error?.response?.status === 400) toast.warning(message);
      else toast.error(message);
    } finally {
      setSaving(false);
    }
  };

  const handleEjecutarOrden = async (orden) => {
    if (!orden?.id) return false;
    const loadingToastId = toast.loading("Ejecutando pago...");
    try {
      setExecutingOrderId(orden.id);
      const response = await ejecutarOrdenPagoProveedor(orden.id);
      toast.dismiss(loadingToastId);
      toast.success(response?.message || "Pago ejecutado exitosamente");
      if (response?.tesoreria_warning) {
        setTesoreriaWarningOpen(response.tesoreria_warning);
      }

      try {
        const blob = await getOrdenPagoProveedorPdf(orden.id);
        openPdfFromBlob(blob, `orden-pago-${orden.numero_orden_pago || "sin-numero"}.pdf`);
      } catch (error) {
        console.error(error);
        toast.warning("El pago se ejecutó, pero no se pudo abrir el PDF automáticamente");
      }

      await Promise.all([loadPagos(), loadDashboard()]);
      return true;
    } catch (error) {
      toast.dismiss(loadingToastId);
      console.error(error);
      const message = error?.response?.data?.message || "No se pudo ejecutar la orden";
      if (error?.response?.status === 400) toast.warning(message);
      else toast.error(message);
      return false;
    } finally {
      setExecutingOrderId(null);
    }
  };

  const handleEnviarAprobacionOrden = async (orden) => {
    if (!orden?.id) return;
    const loadingToastId = toast.loading("Enviando orden a aprobación...");
    try {
      setWorkflowActionId(orden.id);
      const response = await enviarAprobacionOrdenPagoProveedor(orden.id);
      toast.dismiss(loadingToastId);
      toast.success(response?.message || "Orden enviada a aprobación");
      await Promise.all([loadPagos(), loadDashboard()]);
    } catch (error) {
      toast.dismiss(loadingToastId);
      console.error(error);
      const message = error?.response?.data?.message || "No se pudo enviar la orden a aprobación";
      if (error?.response?.status === 400) toast.warning(message);
      else toast.error(message);
    } finally {
      setWorkflowActionId(null);
    }
  };

  const handleAprobarOrden = async (orden) => {
    if (!orden?.id) return false;
    const loadingToastId = toast.loading("Aprobando orden...");
    try {
      setWorkflowActionId(orden.id);
      const response = await aprobarOrdenPagoProveedor(orden.id);
      toast.dismiss(loadingToastId);
      toast.success(response?.message || "Orden aprobada");
      await Promise.all([loadPagos(), loadDashboard()]);
      return true;
    } catch (error) {
      toast.dismiss(loadingToastId);
      console.error(error);
      const message = error?.response?.data?.message || "No se pudo aprobar la orden";
      if (error?.response?.status === 400) toast.warning(message);
      else toast.error(message);
      return false;
    } finally {
      setWorkflowActionId(null);
    }
  };

  const handleRechazarOrden = async (orden) => {
    if (!orden?.id) return;
    const motivo = window.prompt("Motivo de rechazo de la orden de pago:", "Falta respaldo documental");
    if (motivo === null) return;
    const motivoNormalizado = String(motivo || "").trim();
    if (!motivoNormalizado) {
      toast.warning("Debes indicar un motivo para rechazar la orden");
      return;
    }

    const loadingToastId = toast.loading("Rechazando orden...");
    try {
      setWorkflowActionId(orden.id);
      const response = await rechazarOrdenPagoProveedor(orden.id, motivoNormalizado);
      toast.dismiss(loadingToastId);
      toast.success(response?.message || "Orden rechazada");
      await Promise.all([loadPagos(), loadDashboard()]);
    } catch (error) {
      toast.dismiss(loadingToastId);
      console.error(error);
      const message = error?.response?.data?.message || "No se pudo rechazar la orden";
      if (error?.response?.status === 400) toast.warning(message);
      else toast.error(message);
    } finally {
      setWorkflowActionId(null);
    }
  };

  const handleProveedorChange = (proveedor) => {
    cuotasPrefillRef.current = null;
    setSelectedProveedor(proveedor || null);
    setOrderForm((prev) => ({
      ...prev,
      proveedor_id: proveedor?.id || "",
    }));
    setCuentasPagoConfig({});
  };

  const requiereAprobacionOrden = Boolean(
    configCompras.workflow_obligatorio ||
      ((configCompras.requiere_aprobacion || configCompras.usar_workflow) &&
        !configCompras.permite_pago_sin_aprobacion),
  );
  const aplicaPagoAlGuardar = Boolean(configCompras.aplicar_pago_al_guardar) && !requiereAprobacionOrden;

  // Dialog de datos adicionales del medio de pago (compartido entre vistas)
  const datosMedioDialogNode = datosMedioDialog.open && (() => {
    const dId = datosMedioDialog.cuentaId;
    const dCuenta = cuentasById.get(dId);
    const dConfig = cuentasPagoConfig[dId] || initCuentaPagoConfig();
    const dMedio = mediosPago.find((m) => m.id === dConfig.medio_pago_id);
    const dEsCheque = isMedioCheque(dMedio);
    const dEsTarjeta = isMedioTarjeta(dMedio);
    const dEsTransferencia = isMedioTransferencia(dMedio);
    const dEsDeposito = isMedioDeposito(dMedio);
    const upd = (field, val) => updateCuentaPagoConfig(dId, field, val);
    const cerrar = () => setDatosMedioDialog({ open: false, cuentaId: null });

    return (
      <Dialog open onClose={cerrar} maxWidth="sm" fullWidth PaperProps={{ sx: { borderRadius: 2 } }}>
        <DialogTitle sx={{ pb: 0.5 }}>
          Datos del medio de pago
          <Typography variant="caption" color="text.secondary" sx={{ display: "block" }}>
            {getCuentaDocumentoRef(dCuenta)} — {dMedio?.descripcion || dMedio?.nombre || ""}
          </Typography>
        </DialogTitle>
        <DialogContent sx={{ pt: 2 }}>
          <Box sx={{ display: "grid", gap: 2, gridTemplateColumns: "1fr 1fr", mt: 1 }}>

            {dEsCheque && (<>
              <TextField
                select
                size="small"
                label="Cuenta tesorería *"
                value={dConfig.cuenta_bancaria_id || ""}
                onChange={(e) => upd("cuenta_bancaria_id", e.target.value)}
                sx={{ gridColumn: "1/-1" }}
                helperText="Cartera donde queda registrado el cheque emitido"
              >
                {cuentasBancarias.map((cb) => (
                  <MenuItem key={cb.id} value={cb.id}>{cb.nombre}</MenuItem>
                ))}
              </TextField>
              <TextField
                size="small"
                label="N° Cheque *"
                value={dConfig.numero_cheque || ""}
                onChange={(e) => upd("numero_cheque", e.target.value.replace(/[^\d]/g, "").slice(0, 30))}
                inputProps={{ maxLength: 30 }}
                helperText="Ej: 0012345"
              />
              <BancoSelect
                label="Banco emisor *"
                value={dConfig.banco_emisor || ""}
                onChange={(v) => upd("banco_emisor", v)}
                helperText="Seleccioná o escribí"
              />
              <TextField
                size="small"
                label="Titular *"
                value={dConfig.titular_cheque || ""}
                onChange={(e) => upd("titular_cheque", e.target.value)}
                inputProps={{ maxLength: 150 }}
                helperText="Nombre del firmante"
              />
              <TextField
                size="small"
                label="N° Cuenta"
                value={dConfig.numero_operacion || ""}
                onChange={(e) => upd("numero_operacion", e.target.value)}
                inputProps={{ maxLength: 50 }}
                helperText="Opcional"
              />
              <TextField
                size="small"
                type="date"
                label="Fecha emisión *"
                value={dConfig.fecha_emision_cheque || ""}
                onChange={(e) => upd("fecha_emision_cheque", e.target.value)}
                InputLabelProps={{ shrink: true }}
              />
              <TextField
                size="small"
                type="date"
                label="Fecha cobro / venc."
                value={dConfig.fecha_vencimiento_cheque || ""}
                onChange={(e) => upd("fecha_vencimiento_cheque", e.target.value)}
                InputLabelProps={{ shrink: true }}
                helperText="Si es futura → diferido"
              />
            </>)}

            {dEsTarjeta && (<>
              <TextField
                select
                size="small"
                label="Tarjeta *"
                value={dConfig.tarjeta_id || ""}
                onChange={(e) => upd("tarjeta_id", e.target.value)}
                sx={{ gridColumn: "1/-1" }}
              >
                {tarjetas.map((t) => (
                  <MenuItem key={t.id} value={t.id}>{t.descripcion}</MenuItem>
                ))}
              </TextField>
              <TextField
                size="small"
                label="Últimos 4 dígitos *"
                value={dConfig.numero_tarjeta || ""}
                onChange={(e) => upd("numero_tarjeta", e.target.value.replace(/[^\d]/g, "").slice(0, 4))}
                inputProps={{ maxLength: 4 }}
                helperText="Ej: 1234"
                sx={{ gridColumn: "1/-1" }}
              />
            </>)}

            {(dEsTransferencia || dEsDeposito) && (<>
              <TextField
                select
                size="small"
                label={dEsDeposito ? "Cuenta bancaria destino *" : "Cuenta bancaria origen *"}
                value={dConfig.cuenta_bancaria_id || ""}
                onChange={(e) => upd("cuenta_bancaria_id", e.target.value)}
                sx={{ gridColumn: "1/-1" }}
                helperText={dEsDeposito ? "Cuenta donde se deposita el pago" : "Cuenta desde donde se realiza la transferencia"}
              >
                {cuentasBancarias.map((cb) => (
                  <MenuItem key={cb.id} value={cb.id}>
                    {cb.nombre}{cb.numero_cuenta ? ` — ${cb.numero_cuenta}` : ""}
                  </MenuItem>
                ))}
              </TextField>
              {dEsTransferencia && (
                <TextField
                  size="small"
                  label="N° Operación / referencia"
                  value={dConfig.numero_operacion || ""}
                  onChange={(e) => upd("numero_operacion", e.target.value)}
                  inputProps={{ maxLength: 100 }}
                  helperText="Ej: TRF-123456"
                  sx={{ gridColumn: "1/-1" }}
                />
              )}
            </>)}

          </Box>
        </DialogContent>
        <DialogActions sx={{ px: 3, pb: 2 }}>
          <Button onClick={cerrar}>Cancelar</Button>
          <Button variant="contained" onClick={cerrar}>Confirmar</Button>
        </DialogActions>
      </Dialog>
    );
  })();

  if (showForm) {
    return (
      <Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
        <Paper variant="outlined" sx={{ p: { xs: 1.5, sm: 2 } }}>
          <Box
            sx={{
              display: "flex",
              justifyContent: "space-between",
              alignItems: { xs: "flex-start", sm: "center" },
              flexDirection: { xs: "column", sm: "row" },
              gap: 1,
              mb: 2,
            }}
          >
            <Typography variant="h6" sx={{ display: "flex", alignItems: "center", gap: 1 }}>
              <Icon icon="mdi:cash-multiple" /> Nueva Orden de Pago
            </Typography>
            <Button
              variant="outlined"
              onClick={handleCloseForm}
              startIcon={<Icon icon="mdi:close" />}
              sx={{ textTransform: "none" }}
            >
              Cerrar
            </Button>
          </Box>

          <Box
            sx={{
              display: "grid",
              gridTemplateColumns: {
                xs: "1fr",
                md: "repeat(2, minmax(0, 1fr))",
                xl: "repeat(3, minmax(0, 1fr))",
              },
              gap: { xs: 1.5, sm: 2 },
            }}
          >
            <Box sx={{ minWidth: 0 }}>
              <TextField
                select
                label="Sucursal"
                value={orderForm.sucursal_id}
                onChange={(e) => setOrderForm((prev) => ({ ...prev, sucursal_id: e.target.value }))}
                fullWidth
                size="small"
                sx={ORDER_FIELD_INPUT_SX}
              >
                <MenuItem value="">Seleccionar</MenuItem>
                {sucursales.map((sucursal) => (
                  <MenuItem key={sucursal.id} value={sucursal.id}>
                    {sucursal.descripcion || sucursal.punto_establecimiento || "Sucursal"}
                  </MenuItem>
                ))}
              </TextField>
            </Box>

            <Box sx={{ minWidth: 0 }}>
              <Box
                sx={{
                  "& .MuiOutlinedInput-root": {
                    minHeight: 42,
                    borderRadius: "8px",
                    backgroundColor: "rgba(255,255,255,0.03)",
                  },
                }}
              >
                <ProveedorSelector
                  value={selectedProveedor}
                  onChange={handleProveedorChange}
                  label="Proveedor"
                  required
                  minWidth={0}
                  contexto="todos"
                />
              </Box>
            </Box>

            <Box sx={{ minWidth: 0 }}>
              <TextField
                type="date"
                label="Fecha de pago"
                InputLabelProps={{ shrink: true }}
                value={orderForm.fecha_pago}
                onChange={(e) => setOrderForm((prev) => ({ ...prev, fecha_pago: e.target.value }))}
                fullWidth
                size="small"
                sx={ORDER_FIELD_INPUT_SX}
              />
            </Box>

            <Box sx={{ minWidth: 0 }}>
              <TextField
                select
                label="Moneda"
                value={orderForm.moneda_id}
                onChange={(e) => setOrderForm((prev) => ({ ...prev, moneda_id: e.target.value }))}
                fullWidth
                size="small"
                sx={ORDER_FIELD_INPUT_SX}
              >
                <MenuItem value="">Seleccionar</MenuItem>
                {monedas.map((moneda) => (
                  <MenuItem key={moneda.id} value={moneda.id}>
                    {moneda.codigo} - {moneda.descripcion}
                    {moneda.es_principal ? " ★" : ""}
                  </MenuItem>
                ))}
              </TextField>
            </Box>

            <Box sx={{ minWidth: 0 }}>
              <TextField
                select
                label="Medio de pago por defecto"
                value={orderForm.medio_pago_id}
                onChange={(e) => {
                  const value = e.target.value;
                  setOrderForm((prev) => ({ ...prev, medio_pago_id: value }));
                  setCuentasPagoConfig((prev) => {
                    const next = { ...prev };
                    selectedCuentaIds.forEach((cuentaId) => {
                      const current = next[cuentaId] || initCuentaPagoConfig(cuentaId);
                      if (!current.medio_pago_id) {
                        next[cuentaId] = { ...current, medio_pago_id: value };
                      }
                    });
                    return next;
                  });
                }}
                fullWidth
                size="small"
                sx={ORDER_FIELD_INPUT_SX}
              >
                <MenuItem value="">Seleccionar</MenuItem>
                {mediosPago.map((medio) => (
                  <MenuItem key={medio.id} value={medio.id}>
                    {medio.descripcion || medio.nombre}
                  </MenuItem>
                ))}
              </TextField>
            </Box>

            <Box sx={{ minWidth: 0 }}>
              <TextField
                type="number"
                label="Cotización"
                value={orderForm.cotizacion}
                onChange={(e) => {
                  setCotizacionTocada(true);
                  setOrderForm((prev) => ({ ...prev, cotizacion: e.target.value }));
                }}
                fullWidth
                size="small"
                inputProps={{ min: 0, step: "0.000001" }}
                sx={ORDER_FIELD_INPUT_SX}
                disabled={monedaSeleccionadaCodigo === "PYG"}
              />
              {monedaSeleccionadaCodigo && monedaSeleccionadaCodigo !== "PYG" && (
                <CotizacionHint cotizacion={cotizacionVigente} tocado={cotizacionTocada} />
              )}
            </Box>

            <Box sx={{ minWidth: 0 }}>
              <TextField
                label="Referencia"
                value={orderForm.referencia}
                onChange={(e) => setOrderForm((prev) => ({ ...prev, referencia: e.target.value }))}
                fullWidth
                size="small"
                inputProps={{ maxLength: 100 }}
                sx={ORDER_FIELD_INPUT_SX}
              />
            </Box>
          </Box>

          <Box sx={{ mt: { xs: 1.5, sm: 2 } }}>
            <TextField
              label="Observaciones"
              value={orderForm.observaciones}
              onChange={(e) => setOrderForm((prev) => ({ ...prev, observaciones: e.target.value }))}
              fullWidth
              multiline
              minRows={2}
              size="small"
              sx={ORDER_FIELD_INPUT_SX}
            />
          </Box>
        </Paper>

        <Paper variant="outlined" sx={{ p: { xs: 1.5, sm: 2 } }}>
          <Typography variant="subtitle1" sx={{ mb: 1, display: "flex", alignItems: "center", gap: 1 }}>
            <Icon icon="mdi:file-document-multiple-outline" /> Cuentas por pagar seleccionables
          </Typography>
          {planPagosActivo && cuentasPendientes.length > 0 && (
            <Typography variant="body2" color="text.secondary" sx={{ mb: 1.5 }}>
              Vienen marcadas las cuotas programadas en el plan de pagos hasta el {fmtFechaCalendario(finPeriodoPagoActualISO(configCompras))}. Las demás se marcan a mano.
            </Typography>
          )}

          {hayMonedasMezcladas && (
            <Alert
              severity="error"
              icon={<Icon icon="mdi:alert-circle-outline" />}
              sx={{ mb: 1.5 }}
            >
              <strong>Monedas mezcladas:</strong> seleccionaste cuentas en{" "}
              <strong>{monedasEnSeleccion.join(" y ")}</strong>. Una orden de pago sólo puede
              cerrar cuentas de una misma moneda. Emití una orden por moneda o desmarcá las de
              otra moneda para continuar.
            </Alert>
          )}
          {monedaFormDesalineada && (
            <Alert
              severity="warning"
              icon={<Icon icon="mdi:currency-usd-off" />}
              sx={{ mb: 1.5 }}
            >
              La moneda del formulario (<strong>{monedaFormCodigo}</strong>) no coincide con la
              moneda de las cuentas seleccionadas (<strong>{monedaSeleccionCodigo}</strong>). Se
              va a auto-corregir al guardar; si querés controlar manualmente, ajustá el campo{" "}
              <strong>MONEDA</strong> arriba.
            </Alert>
          )}

          {loadingPendientes ? (
            <Box sx={{ py: 2 }}>
              <Skeleton height={40} />
              <Skeleton height={40} />
              <Skeleton height={40} />
            </Box>
          ) : cuentasPendientes.length === 0 ? (
            <Typography variant="body2" color="text.secondary">
              {selectedProveedor?.id
                ? "El proveedor no tiene cuentas pendientes"
                : "Seleccioná un proveedor para cargar cuentas pendientes"}
            </Typography>
          ) : (
            <TableContainer component={Paper} variant="outlined" sx={{ mb: 2 }}>
              <Table size="small">
                <TableHead>
                  <TableRow>
                    <TableCell padding="checkbox">
                      <input
                        type="checkbox"
                        checked={cuentasLibres.length > 0 && selectedCuentaIds.length === cuentasLibres.length}
                        onChange={toggleAllCuentas}
                      />
                    </TableCell>
                    <TableCell>Documento</TableCell>
                    <TableCell>Origen</TableCell>
                    <TableCell>Cuota</TableCell>
                    <TableCell>Vencimiento</TableCell>
                    {planPagosActivo && <TableCell>Programada para</TableCell>}
                    <TableCell>Medio de pago</TableCell>
                    <TableCell>Datos del medio</TableCell>
                    <TableCell>Referencia</TableCell>
                    <TableCell align="right">Saldo pendiente</TableCell>
                    <TableCell align="right">Monto a pagar</TableCell>
                  </TableRow>
                </TableHead>
                <TableBody>
                  {cuentasPendientes.map((cuenta) => {
                    const moneda = cuenta.moneda?.simbolo || "Gs.";
                    const saldo = parseNumber(cuenta.saldo_pendiente, 0);
                    const checked = selectedCuentaIds.includes(cuenta.id);
                    const pagoConfig = cuentasPagoConfig[cuenta.id] || initCuentaPagoConfig(cuenta.id);
                    const permitePagoParcial = Boolean(configCompras.permitir_pago_parcial);
                    const montoConfigurado = parseNumber(pagoConfig.monto, saldo);
                    const montoValido = Math.max(0, Math.min(saldo, montoConfigurado));
                    const medioSeleccionado = mediosPago.find(
                      (medio) => medio.id === pagoConfig.medio_pago_id,
                    );
                    const mostrarCheque = isMedioCheque(medioSeleccionado);
                    const mostrarTarjeta = isMedioTarjeta(medioSeleccionado);
                    const mostrarTransferencia = isMedioTransferencia(medioSeleccionado);
                    const mostrarDeposito = isMedioDeposito(medioSeleccionado);
                    return (
                      <TableRow key={cuenta.id} hover sx={cuenta.orden_abierta ? { opacity: 0.6 } : undefined}>
                        <TableCell padding="checkbox">
                          <input
                            type="checkbox"
                            checked={checked}
                            disabled={Boolean(cuenta.orden_abierta)}
                            onChange={() => toggleCuenta(cuenta.id)}
                            aria-label={`Incluir ${getCuentaDocumentoRef(cuenta)}`}
                          />
                        </TableCell>
                        <TableCell>
                          {getCuentaDocumentoRef(cuenta)}
                          {cuenta.orden_abierta && (
                            <Tooltip title="Una cuota no puede estar en dos órdenes de pago a la vez. Para liberarla, anulá esa orden.">
                              <Chip size="small" color="warning" variant="outlined" label={`En ${describirOrdenAbierta(cuenta.orden_abierta)}`} sx={{ ml: 1, height: 22, fontSize: "0.7rem" }} />
                            </Tooltip>
                          )}
                        </TableCell>
                        <TableCell>
                          <Chip
                            size="small"
                            variant="outlined"
                            color={getCuentaOrigenTipo(cuenta) === "gasto" ? "secondary" : "info"}
                            label={getCuentaOrigenLabel(cuenta)}
                            sx={{ minWidth: 72, fontSize: "0.72rem", height: 24 }}
                          />
                        </TableCell>
                        <TableCell>{cuenta.numero_cuota || 1}</TableCell>
                        <TableCell>{formatDate(cuenta.fecha_vencimiento)}</TableCell>
                        {planPagosActivo && (
                          <TableCell sx={{ whiteSpace: "nowrap", color: cuenta.fecha_pago_programada ? "text.primary" : "text.disabled" }}>
                            {cuenta.fecha_pago_programada ? fmtFechaCalendario(cuenta.fecha_pago_programada) : "Sin programar"}
                          </TableCell>
                        )}
                        <TableCell sx={{ minWidth: 180 }}>
                          <TextField
                            select
                            size="small"
                            fullWidth
                            value={pagoConfig.medio_pago_id || ""}
                            disabled={!checked}
                            onChange={(e) =>
                              updateCuentaPagoConfig(cuenta.id, "medio_pago_id", e.target.value)
                            }
                          >
                            <MenuItem value="">Seleccionar</MenuItem>
                            {mediosPago.map((medio) => (
                              <MenuItem key={medio.id} value={medio.id}>
                                {medio.descripcion || medio.nombre}
                              </MenuItem>
                            ))}
                          </TextField>
                        </TableCell>
                        <TableCell sx={{ minWidth: 160 }}>
                          {(mostrarCheque || mostrarTarjeta || mostrarTransferencia || mostrarDeposito) ? (() => {
                            const completo = getDatosMedioCompleto(pagoConfig, medioSeleccionado);
                            const resumen = getDatosMedioResumen(pagoConfig, medioSeleccionado, cuentasBancarias, tarjetas);
                            return (
                              <Box>
                                <Button
                                  size="small"
                                  variant="text"
                                  color={completo ? "success" : "warning"}
                                  disabled={!checked}
                                  onClick={() => setDatosMedioDialog({ open: true, cuentaId: cuenta.id })}
                                  startIcon={<Icon icon="mdi:eye-outline" />}
                                  sx={{ textTransform: "none", whiteSpace: "nowrap" }}
                                >
                                  Ver detalles
                                </Button>
                                {resumen && (
                                  <Typography variant="caption" color="text.secondary" sx={{ display: "block", mt: 0.25, maxWidth: 200, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                                    {resumen}
                                  </Typography>
                                )}
                              </Box>
                            );
                          })() : (
                            <Typography variant="caption" color="text.secondary">—</Typography>
                          )}
                        </TableCell>
                        <TableCell sx={{ minWidth: 180 }}>
                          <TextField
                            size="small"
                            fullWidth
                            value={pagoConfig.referencia || ""}
                            disabled={!checked}
                            onChange={(e) =>
                              updateCuentaPagoConfig(cuenta.id, "referencia", e.target.value)
                            }
                            inputProps={{ maxLength: 100 }}
                            placeholder="Referencia"
                          />
                        </TableCell>
                        <TableCell align="right">
                          {formatCurrency(cuenta.saldo_pendiente, moneda)}
                        </TableCell>
                        <TableCell align="right" sx={{ minWidth: 180 }}>
                          <MonedaInput
                            size="small"
                            value={montoValido}
                            moneda={cuenta.moneda?.codigo || "PYG"}
                            max={saldo}
                            disabled={!checked || !permitePagoParcial}
                            onChange={(num) => {
                              const bounded = Math.max(0, Math.min(saldo, parseNumber(num, 0)));
                              updateCuentaPagoConfig(cuenta.id, "monto", bounded);
                            }}
                            sx={{ minWidth: 140 }}
                            InputProps={{
                              startAdornment: (
                                <InputAdornment position="start">{moneda}</InputAdornment>
                              ),
                            }}
                          />
                        </TableCell>
                      </TableRow>
                    );
                  })}
                </TableBody>
              </Table>
            </TableContainer>
          )}

          {!configCompras.permitir_pago_parcial && (
            <Typography variant="caption" color="text.secondary" sx={{ display: "block", mb: 1 }}>
              Pago parcial desactivado en configuración: cada línea se pagará por el saldo completo pendiente.
            </Typography>
          )}

          <Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: 1 }}>
            <Typography variant="h6">
              Total selección: {fmtMoneda(totalSeleccionado, monedas.find((m) => m.id === orderForm.moneda_id)?.codigo || "PYG")}
            </Typography>
            <Box
              sx={{
                display: "flex",
                gap: 1,
                width: { xs: "100%", sm: "auto" },
                "& > button": {
                  flex: { xs: 1, sm: "none" },
                },
              }}
            >
              <Button variant="outlined" onClick={handleCloseForm}>
                Cancelar
              </Button>
              <Tooltip
                title={
                  hayMonedasMezcladas
                    ? "No podés guardar: hay cuentas de distintas monedas seleccionadas"
                    : ""
                }
                enterDelay={300}
              >
                <span>
                  <Button
                    variant="contained"
                    onClick={handleRequestSubmit}
                    disabled={saving || selectedCuentaIds.length === 0 || hayMonedasMezcladas}
                    startIcon={<Icon icon="mdi:content-save" />}
                  >
                    {saving ? "Guardando..." : "Guardar orden"}
                  </Button>
                </span>
              </Tooltip>
            </Box>
          </Box>
        </Paper>

        <ConfirmDialog
          open={saveConfirmOpen}
          onClose={closeSaveConfirm}
          onConfirm={handleConfirmSubmit}
          loading={saving}
          title={aplicaPagoAlGuardar ? "Confirmar ejecución de pago" : "Confirmar guardado de orden"}
          message={(
            <Box sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
              <Typography variant="body2">
                Se registrará una orden para el proveedor <strong>{pendingCreateOrder?.proveedorNombre || "-"}</strong>.
              </Typography>
              <Typography variant="body2" color="text.secondary">
                Modo actual:{" "}
                <strong>
                  {aplicaPagoAlGuardar
                    ? "Aplicar pago al guardar"
                    : requiereAprobacionOrden
                      ? "Guardar borrador y enviar a aprobación"
                      : "Guardar como borrador"}
                </strong>
              </Typography>
              <Typography variant="body2" color="text.secondary">
                Cuentas seleccionadas: <strong>{pendingCreateOrder?.cantidadCuentas || 0}</strong>
              </Typography>
              <Typography variant="body2" color="text.secondary">
                Medios de pago utilizados: <strong>{pendingCreateOrder?.cantidadMedios || 0}</strong>
              </Typography>
              <Typography variant="body2" color="text.secondary">
                Total a aplicar: <strong>{fmtMoneda(pendingCreateOrder?.total || 0, pendingCreateOrder?.monedaCodigo || "PYG")}</strong>
              </Typography>
            </Box>
          )}
          confirmText={aplicaPagoAlGuardar ? "Sí, guardar y ejecutar" : "Sí, guardar borrador"}
          cancelText="Revisar"
          confirmColor="primary"
        />

        <Dialog open={Boolean(pdfPreview?.url)} onClose={closePdfPreview} maxWidth="lg" fullWidth>
          <DialogTitle sx={{ display: "flex", alignItems: "center", gap: 1 }}>
            <Icon icon="mdi:file-pdf-box" />
            Vista previa de Comprobante PDF
          </DialogTitle>
          <DialogContent dividers sx={{ p: 0 }}>
            {pdfPreview?.url && (
              <Box sx={{ width: "100%", height: { xs: "68vh", md: "80vh" } }}>
                <iframe
                  src={pdfPreview.url}
                  title="Comprobante de pago PDF"
                  style={{ width: "100%", height: "100%", border: "none", display: "block" }}
                />
              </Box>
            )}
          </DialogContent>
          <DialogActions>
            <Button onClick={closePdfPreview}>Cerrar</Button>
            <Button variant="contained" onClick={handleDownloadPdfPreview} startIcon={<Icon icon="mdi:download" />}>
              Descargar
            </Button>
          </DialogActions>
        </Dialog>

        {datosMedioDialogNode}
      </Box>
    );
  }

  return (
    <Box>
      <Box sx={{ mb: 3 }}>
        <ScreenGuia
          titulo="¿Cómo funciona la orden de pago?"
          intro="Agrupá una o varias facturas de proveedor en una sola orden de pago. Al ejecutarla, Tesorería y Contabilidad se actualizan automáticamente según el medio de pago utilizado."
          pasos={GUIA_PASOS}
          notas={GUIA_NOTAS}
        />
      </Box>

      <Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", mb: 2, flexWrap: "wrap", gap: 1 }}>
        <Box>
          <Typography variant="subtitle1" fontWeight={700}>Órdenes de Pago</Typography>
          <Typography variant="caption" color="text.secondary">
            Agrupá facturas de proveedor en una orden de pago; al ejecutarla se actualizan Tesorería y Contabilidad.
          </Typography>
        </Box>
        <Button variant="contained" onClick={handleOpenForm} startIcon={<Icon icon="mdi:plus" />}>
          Nueva orden
        </Button>
      </Box>

      <ListToolbar
        searchText={searchText}
        onSearchChange={(v) => {
          setSearchText(v);
          setPage(1);
        }}
        searchPlaceholder="Buscar por número, proveedor, factura..."
        showFilters={showFilters}
        onToggleFilters={() => setShowFilters((prev) => !prev)}
        filtrosActivos={filtrosActivos}
        onRefresh={() => {
          loadPagos();
          loadDashboard();
        }}
        quickFilters={[
          { label: "Hoy", value: "hoy" },
          { label: "Ayer", value: "ayer" },
          { label: "Esta semana", value: "semana" },
          { label: "Este mes", value: "mes" },
          { label: "Mes anterior", value: "mes_anterior" },
        ]}
        quickFilterActive={filtroRapido}
        onQuickFilter={aplicarFiltroRapido}
        onClearFilters={limpiarFiltros}
      />

      <Collapse in={showFilters}>
        <Paper sx={{ p: { xs: 1.5, sm: 2 }, mb: 2, overflow: "hidden" }} variant="outlined">
          <Box sx={{ display: "flex", flexDirection: "column", gap: 1.5 }}>
            <Box sx={{ display: "flex", gap: 1.5, flexWrap: "wrap" }}>
              <Box sx={{ flex: 1, minWidth: { xs: "100%", sm: 160 } }}>
                <TextField
                  label="Fecha desde"
                  type="date"
                  value={fechaDesde}
                  onChange={(e) => {
                    setFechaDesde(e.target.value);
                    setFiltroRapido("");
                    setPage(1);
                  }}
                  size="small"
                  fullWidth
                  InputLabelProps={{ shrink: true }}
                />
              </Box>
              <Box sx={{ flex: 1, minWidth: { xs: "100%", sm: 160 } }}>
                <TextField
                  label="Fecha hasta"
                  type="date"
                  value={fechaHasta}
                  onChange={(e) => {
                    setFechaHasta(e.target.value);
                    setFiltroRapido("");
                    setPage(1);
                  }}
                  size="small"
                  fullWidth
                  InputLabelProps={{ shrink: true }}
                />
              </Box>
            </Box>
            <Box sx={{ display: "flex", gap: 1.5, flexWrap: "wrap" }}>
              <FormControl sx={{ flex: 1, minWidth: { xs: "100%", sm: 160 } }} size="small">
                <InputLabel>Estado</InputLabel>
                <Select
                  value={estadoFilter}
                  label="Estado"
                  onChange={(e) => {
                    setEstadoFilter(e.target.value);
                    setPage(1);
                  }}
                >
                  <MenuItem value="">Todos los estados</MenuItem>
                  <MenuItem value="borrador">Borrador</MenuItem>
                  <MenuItem value="pendiente_aprobacion">Pend. aprobación</MenuItem>
                  <MenuItem value="pendiente">Aprobada</MenuItem>
                  <MenuItem value="rechazada">Rechazada</MenuItem>
                  <MenuItem value="pagado">Pagada</MenuItem>
                  <MenuItem value="anulada">Anulada</MenuItem>
                </Select>
              </FormControl>
              <FormControl sx={{ flex: 1, minWidth: { xs: "100%", sm: 140 } }} size="small">
                <InputLabel>Límite</InputLabel>
                <Select
                  value={String(limit)}
                  label="Límite"
                  onChange={(e) => {
                    setLimit(parseNumber(e.target.value, 20));
                    setPage(1);
                  }}
                >
                  <MenuItem value="10">10</MenuItem>
                  <MenuItem value="20">20</MenuItem>
                  <MenuItem value="50">50</MenuItem>
                </Select>
              </FormControl>
              <Button
                variant="outlined"
                onClick={limpiarFiltros}
                startIcon={<Icon icon="mdi:filter-off" />}
                sx={{
                  flex: { xs: 1, sm: "none" },
                  minWidth: { xs: 0, sm: 120 },
                }}
              >
                Limpiar
              </Button>
            </Box>
          </Box>
        </Paper>
      </Collapse>

      <Grid container spacing={{ xs: 1, sm: 2 }} sx={{ mb: { xs: 2, sm: 3 } }}>
        <Grid size={{ xs: 6, sm: 3 }}>
          <Card variant="outlined" sx={{ height: "100%" }}>
            <CardContent sx={{ p: { xs: 1, sm: 1.5 }, "&:last-child": { pb: { xs: 1, sm: 1.5 } } }}>
              <Typography color="text.secondary" variant="caption" sx={{ display: "flex", alignItems: "center", gap: 0.5 }}>
                <Icon icon="mdi:file-document" width={isMobile ? 14 : 16} /> Órdenes
              </Typography>
              <Typography variant={isMobile ? "h6" : "h5"} fontWeight={600}>
                {loadingDashboard ? <Skeleton width={40} /> : dashboard.total}
              </Typography>
            </CardContent>
          </Card>
        </Grid>

        <Grid size={{ xs: 6, sm: 3 }}>
          <Card variant="outlined" sx={{ height: "100%" }}>
            <CardContent sx={{ p: { xs: 1, sm: 1.5 }, "&:last-child": { pb: { xs: 1, sm: 1.5 } } }}>
              <Typography color="text.secondary" variant="caption" sx={{ display: "flex", alignItems: "center", gap: 0.5 }}>
                <Icon icon="mdi:cash" width={isMobile ? 14 : 16} /> Monto aplicado
              </Typography>
              <Box sx={{ display: "flex", flexDirection: "column", gap: 0.25 }}>
                {loadingDashboard ? (
                  <Skeleton width={100} />
                ) : Object.keys(montoAplicadoPorMoneda).length === 0 ? (
                  <Typography variant={isMobile ? "h6" : "h5"} fontWeight={600} color="success.main">
                    {fmtMoneda(0, "PYG")}
                  </Typography>
                ) : (
                  Object.entries(montoAplicadoPorMoneda).map(([code, total]) => (
                    <Typography
                      key={code}
                      variant={isMobile ? "body2" : "h6"}
                      fontWeight={700}
                      color="success.main"
                      sx={{ lineHeight: 1.15 }}
                    >
                      {fmtMoneda(total, code)}
                    </Typography>
                  ))
                )}
              </Box>
            </CardContent>
          </Card>
        </Grid>

        <Grid size={{ xs: 6, sm: 3 }}>
          <Card variant="outlined" sx={{ height: "100%" }}>
            <CardContent sx={{ p: { xs: 1, sm: 1.5 }, "&:last-child": { pb: { xs: 1, sm: 1.5 } } }}>
              <Typography color="text.secondary" variant="caption" sx={{ display: "flex", alignItems: "center", gap: 0.5 }}>
                <Icon icon="mdi:check-circle" width={isMobile ? 14 : 16} /> Pagadas
              </Typography>
              <Typography variant={isMobile ? "h6" : "h5"} fontWeight={600} color="success.main">
                {loadingDashboard ? <Skeleton width={40} /> : dashboard.pagadas}
              </Typography>
            </CardContent>
          </Card>
        </Grid>

        <Grid size={{ xs: 6, sm: 3 }}>
          <Card variant="outlined" sx={{ height: "100%", borderColor: "warning.light" }}>
            <CardContent sx={{ p: { xs: 1, sm: 1.5 }, "&:last-child": { pb: { xs: 1, sm: 1.5 } } }}>
              <Typography color="text.secondary" variant="caption" sx={{ display: "flex", alignItems: "center", gap: 0.5 }}>
                <Icon icon="mdi:file-cancel-outline" width={isMobile ? 14 : 16} /> Anuladas
              </Typography>
              <Typography variant={isMobile ? "h6" : "h5"} fontWeight={600} color="warning.main">
                {loadingDashboard ? <Skeleton width={40} /> : dashboard.anuladas}
              </Typography>
            </CardContent>
          </Card>
        </Grid>
      </Grid>

      <Paper variant="outlined" sx={{ overflow: "hidden", borderRadius: 2 }}>
        {loadingList ? (
          <Box sx={{ p: 2 }}>
            <Skeleton height={44} />
            <Skeleton height={44} />
            <Skeleton height={44} />
          </Box>
        ) : pagos.length === 0 ? (
          <Box sx={{ p: 3 }}>
            <EmptyState
              icon="mdi:cash-multiple"
              title="Sin órdenes de pago en el rango"
              description="Ajustá los filtros o creá una nueva orden desde el botón superior derecho."
              actionLabel="Nueva orden"
              onAction={handleOpenForm}
            />
          </Box>
        ) : (
          isMobile ? (
            <Box sx={{ p: 1, display: "flex", flexDirection: "column", gap: 1 }}>
              {pagos.map((pago) => {
                const proveedor = pago?.proveedores?.personas;
                const estadoInfo = normalizeOrdenEstado(pago?.estado, Boolean(pago?.anulado));
                const isAnulada = estadoInfo.key === "ANULADA";
                const isBorrador = estadoInfo.key === "BORRADOR";
                const isPendienteAprobacion = estadoInfo.key === "PENDIENTE_APROBACION";
                const isRechazada = estadoInfo.key === "RECHAZADA";
                const isPendienteEjecucion = estadoInfo.key === "PENDIENTE";
                const canSendApproval = requiereAprobacionOrden && (isBorrador || isRechazada);
                const canApproveReject = isPendienteAprobacion;
                const canExecute = !requiereAprobacionOrden
                  ? (isBorrador || isPendienteEjecucion)
                  : isPendienteEjecucion;
                const monedaCodigo = pago?.moneda?.codigo || "PYG";
                const compraLabel = pago?.compra_cab
                  ? formatCompraComprobante(pago.compra_cab)
                  : pago?.compra_id
                    ? "Sin número"
                    : "-";

                return (
                  <Box
                    key={pago.id}
                    sx={{
                      border: "1px solid",
                      borderColor: "divider",
                      borderRadius: 2,
                      p: 1.25,
                      backgroundColor: "rgba(255,255,255,0.01)",
                    }}
                  >
                    <Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 1 }}>
                      <Box sx={{ minWidth: 0 }}>
                        <Typography sx={{ fontWeight: 700, fontFamily: "monospace", fontSize: "1.03rem" }}>
                          {pago.numero_orden_pago || "Sin número"}
                        </Typography>
                        <Typography variant="body2" sx={{ fontWeight: 600 }}>
                          {proveedor?.razon_social || "-"}
                        </Typography>
                        <Typography variant="caption" color="text.secondary">
                          {proveedor?.ruc ? `${proveedor.ruc}-${proveedor.dv || 0}` : "-"}
                        </Typography>
                      </Box>
                      <Chip label={estadoInfo.label} size="small" color={estadoInfo.color} variant="outlined" />
                    </Box>

                    <Typography variant="caption" color="text.secondary" sx={{ display: "block", mt: 0.5 }}>
                      Compra: {compraLabel}
                    </Typography>

                    <Box sx={{ mt: 1, display: "flex", justifyContent: "space-between", alignItems: "flex-end", gap: 1 }}>
                      <Box>
                        <Typography sx={{ fontSize: "1.35rem", lineHeight: 1.1, fontWeight: 700, color: "primary.main" }}>
                          {fmtMoneda(pago.monto_total, monedaCodigo)}
                        </Typography>
                        <Typography variant="caption" color="text.secondary">
                          {formatDateTime(pago.fecha_pago)}
                        </Typography>
                      </Box>

                      <Box sx={{ display: "inline-flex", alignItems: "center", gap: 0.5, flexWrap: "wrap", justifyContent: "flex-end" }}>
                        <Tooltip title="Ver detalle">
                          <IconButton size="small" onClick={() => handleViewDetails(pago.id)}>
                            <Icon icon="lucide:eye" width={16} />
                          </IconButton>
                        </Tooltip>
                        <Tooltip title="Ver PDF">
                          <IconButton
                            size="small"
                            onClick={() => handleViewPdf(pago)}
                            disabled={pdfLoadingId === pago.id}
                          >
                            {pdfLoadingId === pago.id ? (
                              <CircularProgress size={18} thickness={5} />
                            ) : (
                              <Icon icon="mdi:file-pdf-box" width={18} />
                            )}
                          </IconButton>
                        </Tooltip>
                        {canSendApproval && (
                          <Tooltip title="Enviar a aprobación">
                            <IconButton
                              size="small"
                              color="info"
                              onClick={() => handleEnviarAprobacionOrden(pago)}
                              disabled={workflowActionId === pago.id}
                            >
                              {workflowActionId === pago.id ? (
                                <CircularProgress size={18} thickness={5} />
                              ) : (
                                <Icon icon="mdi:send-check-outline" width={18} />
                              )}
                            </IconButton>
                          </Tooltip>
                        )}
                        {canApproveReject && (
                          <Tooltip title="Aprobar orden">
                            <IconButton
                              size="small"
                              color="success"
                              onClick={() => requestWorkflowConfirm(pago, "aprobar")}
                              disabled={workflowActionId === pago.id}
                            >
                              {workflowActionId === pago.id ? (
                                <CircularProgress size={18} thickness={5} />
                              ) : (
                                <Icon icon="mdi:check-circle-outline" width={18} />
                              )}
                            </IconButton>
                          </Tooltip>
                        )}
                        {canApproveReject && (
                          <Tooltip title="Rechazar orden">
                            <IconButton
                              size="small"
                              color="warning"
                              onClick={() => handleRechazarOrden(pago)}
                              disabled={workflowActionId === pago.id}
                            >
                              {workflowActionId === pago.id ? (
                                <CircularProgress size={18} thickness={5} />
                              ) : (
                                <Icon icon="mdi:close-circle-outline" width={18} />
                              )}
                            </IconButton>
                          </Tooltip>
                        )}
                        {canExecute && (
                          <Tooltip title="Ejecutar pago">
                            <IconButton
                              size="small"
                              color="success"
                              onClick={() => requestWorkflowConfirm(pago, "ejecutar")}
                              disabled={executingOrderId === pago.id}
                            >
                              {executingOrderId === pago.id ? (
                                <CircularProgress size={18} thickness={5} />
                              ) : (
                                <Icon icon="mdi:play-circle-outline" width={18} />
                              )}
                            </IconButton>
                          </Tooltip>
                        )}
                        {!isAnulada && (
                          <Tooltip title="Anular">
                            <IconButton size="small" color="error" onClick={() => requestAnularOrden(pago)}>
                              <Icon icon="lucide:ban" width={16} />
                            </IconButton>
                          </Tooltip>
                        )}
                      </Box>
                    </Box>
                  </Box>
                );
              })}
            </Box>
          ) : (
            <TableContainer>
              <Table size="small">
                <TableHead>
                  <TableRow>
                    <TableCell sx={{ fontWeight: 600 }}>Número</TableCell>
                    <TableCell sx={{ fontWeight: 600 }}>Fecha</TableCell>
                    <TableCell sx={{ fontWeight: 600 }}>Compra</TableCell>
                    <TableCell sx={{ fontWeight: 600 }}>Proveedor</TableCell>
                    <TableCell sx={{ fontWeight: 600 }} align="right">Total</TableCell>
                    <TableCell sx={{ fontWeight: 600 }}>Estado</TableCell>
                    <TableCell sx={{ fontWeight: 600 }} align="center">Acciones</TableCell>
                  </TableRow>
                </TableHead>
                <TableBody>
                  {pagos.map((pago) => {
                    const proveedor = pago?.proveedores?.personas;
                    const estadoInfo = normalizeOrdenEstado(pago?.estado, Boolean(pago?.anulado));
                    const isAnulada = estadoInfo.key === "ANULADA";
                    const isBorrador = estadoInfo.key === "BORRADOR";
                    const isPendienteAprobacion = estadoInfo.key === "PENDIENTE_APROBACION";
                    const isRechazada = estadoInfo.key === "RECHAZADA";
                    const isPendienteEjecucion = estadoInfo.key === "PENDIENTE";
                    const canSendApproval = requiereAprobacionOrden && (isBorrador || isRechazada);
                    const canApproveReject = isPendienteAprobacion;
                    const canExecute = !requiereAprobacionOrden
                      ? (isBorrador || isPendienteEjecucion)
                      : isPendienteEjecucion;
                    const monedaCodigo = pago?.moneda?.codigo || "PYG";

                    const anuladoSx = isAnulada
                      ? { color: "text.disabled", textDecoration: "line-through" }
                      : {};

                    return (
                      <TableRow key={pago.id} hover>
                        <TableCell>
                          <Typography sx={{ fontFamily: "monospace", fontWeight: 600, ...anuladoSx }}>
                            {pago.numero_orden_pago || "Sin número"}
                          </Typography>
                        </TableCell>
                        <TableCell sx={anuladoSx}>{formatDate(pago.fecha_pago)}</TableCell>
                        <TableCell sx={anuladoSx}>
                          {pago?.compra_cab
                            ? formatCompraComprobante(pago.compra_cab)
                            : pago?.compra_id
                              ? "Sin número"
                              : "-"}
                        </TableCell>
                        <TableCell>
                          <Box sx={{ display: "flex", flexDirection: "column" }}>
                            <Typography variant="body2" sx={{ fontWeight: 600, ...anuladoSx }}>
                              {proveedor?.razon_social || "-"}
                            </Typography>
                            <Typography variant="caption" color="text.secondary" sx={anuladoSx}>
                              {proveedor?.ruc ? `${proveedor.ruc}-${proveedor.dv || 0}` : ""}
                            </Typography>
                          </Box>
                        </TableCell>
                        <TableCell align="right">
                          <Typography
                            sx={{
                              fontWeight: 700,
                              color: isAnulada ? "text.disabled" : "success.main",
                              textDecoration: isAnulada ? "line-through" : undefined,
                            }}
                          >
                            {fmtMoneda(pago.monto_total, monedaCodigo)}
                          </Typography>
                        </TableCell>
                        <TableCell>
                          <Chip
                            label={estadoInfo.label}
                            size="small"
                            color={estadoInfo.color}
                            variant="outlined"
                          />
                        </TableCell>
                        <TableCell align="center">
                          {/* Hasta siete acciones por fila: como iconos había
                              que pasar el mouse por cada uno para saber qué
                              hacía. RowActions con los nombres escritos, igual
                              que en Recibos de Cobro. Ver docs/ui-standards.md. */}
                          <RowActions
                            row={pago}
                            mode="select"
                            actions={[
                              {
                                key: "pdf",
                                label: "Ver PDF",
                                icon:
                                  pdfLoadingId === pago.id ? (
                                    <CircularProgress size={16} thickness={5} />
                                  ) : (
                                    <Icon icon="mdi:file-pdf-box" width={18} />
                                  ),
                                disabled: () => pdfLoadingId === pago.id,
                                onClick: () => handleViewPdf(pago),
                              },
                              {
                                key: "detalle",
                                label: "Ver detalle",
                                icon: <Icon icon="lucide:eye" width={16} />,
                                onClick: () => handleViewDetails(pago.id),
                              },
                              {
                                key: "enviar-aprobacion",
                                label: "Enviar a aprobación",
                                icon: <Icon icon="mdi:send-check-outline" width={18} />,
                                show: () => canSendApproval,
                                disabled: () => workflowActionId === pago.id,
                                onClick: () => handleEnviarAprobacionOrden(pago),
                              },
                              {
                                key: "aprobar",
                                label: "Aprobar orden",
                                color: "success",
                                icon: <Icon icon="mdi:check-circle-outline" width={18} />,
                                show: () => canApproveReject,
                                disabled: () => workflowActionId === pago.id,
                                onClick: () => requestWorkflowConfirm(pago, "aprobar"),
                              },
                              {
                                key: "rechazar",
                                label: "Rechazar orden",
                                color: "warning",
                                icon: <Icon icon="mdi:close-circle-outline" width={18} />,
                                show: () => canApproveReject,
                                disabled: () => workflowActionId === pago.id,
                                onClick: () => handleRechazarOrden(pago),
                              },
                              {
                                key: "ejecutar",
                                label: "Ejecutar pago",
                                color: "success",
                                icon: <Icon icon="mdi:play-circle-outline" width={18} />,
                                show: () => canExecute,
                                disabled: () => executingOrderId === pago.id,
                                onClick: () => requestWorkflowConfirm(pago, "ejecutar"),
                              },
                              {
                                key: "anular",
                                label: "Anular orden",
                                color: "error",
                                icon: <Icon icon="lucide:ban" width={16} />,
                                show: () => !isAnulada,
                                onClick: () => requestAnularOrden(pago),
                              },
                            ]}
                          />
                        </TableCell>
                      </TableRow>
                    );
                  })}
                </TableBody>
              </Table>
            </TableContainer>
          )
        )}
      </Paper>

      <Box
        sx={{
          display: "grid",
          gridTemplateColumns: { xs: "1fr", sm: "1fr auto 1fr" },
          alignItems: "center",
          mt: 2,
          gap: 1,
        }}
      >
        <Typography
          variant="caption"
          color="text.secondary"
          sx={{ justifySelf: { xs: "center", sm: "start" } }}
        >
          {totalPagos > 0 ? `Mostrando ${pagos.length} de ${totalPagos} órdenes` : ""}
        </Typography>
        <Box sx={{ justifySelf: "center" }}>
          {totalPagos > 0 && (
            <Pagination
              count={Math.max(1, totalPages)}
              page={page}
              onChange={(_, v) => setPage(v)}
              size="small"
              color="primary"
            />
          )}
        </Box>
        <Box />
      </Box>

      <Dialog open={detalleOpen} onClose={closeDetalle} maxWidth="md" fullWidth>
        <DialogTitle sx={{ display: "flex", alignItems: "center", gap: 1 }}>
          <Icon icon="mdi:file-document-outline" />
          Detalle de Orden de Pago
        </DialogTitle>
        <DialogContent dividers>
          {detalleLoading ? (
            <Box sx={{ py: 1 }}>
              <Skeleton height={30} />
              <Skeleton height={30} />
              <Skeleton height={30} />
              <Skeleton height={30} />
            </Box>
          ) : !detalleOrden ? (
            <Typography variant="body2" color="text.secondary">
              No se encontró información del pago.
            </Typography>
          ) : (
            <Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
              <Box sx={{ display: "flex", flexWrap: "wrap", gap: 2 }}>
                <Typography variant="body2">
                  Número:{" "}
                  <strong>{detalleOrden?.numero_orden_pago || "Sin número"}</strong>
                </Typography>
                <Typography variant="body2">
                  Fecha: <strong>{formatDate(detalleOrden?.fecha_pago)}</strong>
                </Typography>
                <Typography variant="body2">
                  Proveedor: <strong>{detalleOrden?.proveedores?.personas?.razon_social || "-"}</strong>
                </Typography>
              </Box>

              <Typography variant="body2" color="text.secondary">
                Documentos pagados:{" "}
                <strong>
                  {detalleOrden?.orden_pago_proveedor_det?.length || 0}
                </strong>
              </Typography>

              <Divider />

              {Array.isArray(detalleOrden?.orden_pago_proveedor_det) &&
              detalleOrden.orden_pago_proveedor_det.length > 0 ? (
                <TableContainer component={Paper} variant="outlined">
                  <Table size="small">
                    <TableHead>
                      <TableRow>
                        <TableCell>Documento</TableCell>
                        <TableCell>Origen</TableCell>
                        <TableCell>Cuota</TableCell>
                        <TableCell>Vencimiento</TableCell>
                        <TableCell>Medio</TableCell>
                        <TableCell>Datos medio</TableCell>
                        <TableCell>Referencia</TableCell>
                        <TableCell align="right">Monto</TableCell>
                      </TableRow>
                    </TableHead>
                    <TableBody>
                      {detalleOrden.orden_pago_proveedor_det.map((det) => (
                        <TableRow key={det.id}>
                          <TableCell>{getCuentaDocumentoRef(det?.cuentas_pagar)}</TableCell>
                          <TableCell>
                            <Chip
                              size="small"
                              variant="outlined"
                              color={getCuentaOrigenTipo(det?.cuentas_pagar) === "gasto" ? "secondary" : "info"}
                              label={getCuentaOrigenLabel(det?.cuentas_pagar)}
                              sx={{ minWidth: 72, fontSize: "0.72rem", height: 24 }}
                            />
                          </TableCell>
                          <TableCell>{det?.cuentas_pagar?.numero_cuota || 1}</TableCell>
                          <TableCell>{formatDate(det?.cuentas_pagar?.fecha_vencimiento)}</TableCell>
                          <TableCell>{det?.medio_pago?.descripcion || "-"}</TableCell>
                          <TableCell>{det?.observaciones || "-"}</TableCell>
                          <TableCell>{det?.referencia || detalleOrden?.referencia || "-"}</TableCell>
                          <TableCell align="right">
                            {fmtMoneda(det?.monto, detalleOrden?.moneda?.codigo || "PYG")}
                          </TableCell>
                        </TableRow>
                      ))}
                    </TableBody>
                  </Table>
                </TableContainer>
              ) : (
                <Typography variant="body2" color="text.secondary">
                  Esta orden no tiene detalles de documentos vinculados.
                </Typography>
              )}
            </Box>
          )}
        </DialogContent>
        <DialogActions>
          <Button onClick={closeDetalle}>Cerrar</Button>
        </DialogActions>
      </Dialog>

      <Dialog open={Boolean(pdfPreview?.url)} onClose={closePdfPreview} maxWidth="lg" fullWidth>
        <DialogTitle sx={{ display: "flex", alignItems: "center", gap: 1 }}>
          <Icon icon="mdi:file-pdf-box" />
          Vista previa de Comprobante PDF
        </DialogTitle>
        <DialogContent dividers sx={{ p: 0 }}>
          {pdfPreview?.url && (
            <Box sx={{ width: "100%", height: { xs: "68vh", md: "80vh" } }}>
              <iframe
                src={pdfPreview.url}
                title="Comprobante de pago PDF"
                style={{ width: "100%", height: "100%", border: "none", display: "block" }}
              />
            </Box>
          )}
        </DialogContent>
        <DialogActions>
          <Button onClick={closePdfPreview}>Cerrar</Button>
          <Button variant="contained" onClick={handleDownloadPdfPreview} startIcon={<Icon icon="mdi:download" />}>
            Descargar
          </Button>
        </DialogActions>
      </Dialog>

      {/* Diálogo persistente cuando falta configuración de Tesorería.
          Reemplaza al toast anterior (que desaparecía muy rápido para un aviso
          que impacta reportes financieros). El usuario debe cerrar manualmente
          o ir directo a configurar. */}
      <Dialog
        open={Boolean(tesoreriaWarningOpen)}
        onClose={() => setTesoreriaWarningOpen("")}
        maxWidth="sm"
        fullWidth
      >
        <DialogTitle sx={{ display: "flex", alignItems: "center", gap: 1, color: "warning.main" }}>
          <Icon icon="mdi:alert-outline" />
          Configuración de Tesorería incompleta
        </DialogTitle>
        <DialogContent dividers>
          <Alert severity="warning" sx={{ mb: 2 }}>
            {tesoreriaWarningOpen}
          </Alert>
          <Typography variant="body2" gutterBottom>
            <strong>¿Qué significa?</strong>
          </Typography>
          <Typography variant="body2" color="text.secondary" gutterBottom>
            La orden de pago quedó registrada en <strong>Contabilidad</strong> (asiento contable
            confirmado) y en <strong>Cuentas por Pagar</strong> (saldo cancelado), pero{" "}
            <strong>no se generó el movimiento en Tesorería</strong>. Esto significa que:
          </Typography>
          <Box component="ul" sx={{ pl: 2.5, mt: 0.5, mb: 1.5, color: "text.secondary" }}>
            <Typography variant="body2" component="li">
              El egreso <strong>no aparece</strong> en Caja del Día ni en Movimientos de
              Tesorería.
            </Typography>
            <Typography variant="body2" component="li">
              La Conciliación Bancaria no verá este pago.
            </Typography>
            <Typography variant="body2" component="li">
              Los reportes de Flujo de Caja quedan desactualizados hasta que sincronices
              manualmente.
            </Typography>
          </Box>
          <Typography variant="body2" gutterBottom sx={{ mt: 1.5 }}>
            <strong>Por qué salió este aviso</strong>
          </Typography>
          <Typography variant="body2" color="text.secondary" gutterBottom>
            El sistema decide a qué cuenta de tesorería impactar en este orden:
          </Typography>
          <Box component="ol" sx={{ pl: 2.5, mt: 0.5, mb: 1.5, color: "text.secondary" }}>
            <Typography variant="body2" component="li">
              La <strong>cuenta bancaria cargada en el modal</strong> del medio de pago
              (por ej. al elegir Transferencia). Esta gana siempre.
            </Typography>
            <Typography variant="body2" component="li">
              Si el medio no pide cuenta explícita (Efectivo, Giro), busca una{" "}
              <strong>regla automática</strong> por tipo de operación + medio de pago.
            </Typography>
            <Typography variant="body2" component="li">
              Si tampoco existe la regla → aparece este aviso.
            </Typography>
          </Box>
          <Typography variant="body2" gutterBottom sx={{ mt: 1.5 }}>
            <strong>Cómo resolverlo</strong>
          </Typography>
          <Typography variant="body2" color="text.secondary">
            En <strong>Configuración → Tesorería → Reglas Automáticas</strong>, creá una regla
            para el tipo de operación <strong>PAGO_PROVEEDOR</strong> apuntando a la cuenta
            operativa por defecto (Caja General para efectivo/giro, Banco X para
            transferencias). Podés crear reglas separadas por medio de pago para afinar. A
            partir de la regla, las próximas OPs generan el movimiento automáticamente sin más
            configuración por-pago.
          </Typography>
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setTesoreriaWarningOpen("")}>Entendido</Button>
          <Button
            variant="contained"
            color="warning"
            startIcon={<Icon icon="mdi:cog-outline" />}
            onClick={() => {
              setTesoreriaWarningOpen("");
              navigate("/configuracion?seccion=tes-reglas-config");
            }}
          >
            Ir a configurar
          </Button>
        </DialogActions>
      </Dialog>

      <ConfirmDialog
        open={anularConfirmOpen}
        onClose={closeAnularConfirm}
        onConfirm={handleConfirmAnularOrden}
        loading={anulandoOrden}
        title="Confirmar anulación de orden de pago"
        message={(
          <Box sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
            <Typography variant="body2">
              Vas a anular la orden{" "}
              <strong>{pendingAnularOrden?.numero_orden_pago || "sin número"}</strong>.
            </Typography>
            <Typography variant="body2" color="text.secondary">
              Se revertirán los saldos aplicados en cuentas por pagar relacionadas.
            </Typography>
            <Typography variant="body2" color="text.secondary">
              Proveedor: <strong>{pendingAnularOrden?.proveedores?.personas?.razon_social || "-"}</strong> | Total:{" "}
              <strong>{fmtMoneda(pendingAnularOrden?.monto_total, pendingAnularOrden?.moneda?.codigo || "PYG")}</strong>
            </Typography>
            <Typography variant="body2" color="warning.main" sx={{ fontWeight: 600 }}>
              Esta acción impacta el estado de la compra asociada.
            </Typography>
          </Box>
        )}
        confirmText="Sí, anular orden"
        cancelText="Volver"
        confirmColor="error"
      />

      <ConfirmDialog
        open={workflowConfirmOpen}
        onClose={closeWorkflowConfirm}
        onConfirm={handleConfirmWorkflowAction}
        loading={
          (workflowConfirmType === "aprobar" && workflowActionId === pendingWorkflowOrden?.id) ||
          (workflowConfirmType === "ejecutar" && executingOrderId === pendingWorkflowOrden?.id)
        }
        title={workflowConfirmType === "aprobar" ? "Confirmar aprobación de orden" : "Confirmar ejecución de pago"}
        message={(
          <Box sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
            <Typography variant="body2">
              {workflowConfirmType === "aprobar"
                ? "Vas a aprobar esta orden de pago."
                : "Vas a ejecutar el pago de esta orden."}
            </Typography>
            <Typography variant="body2" color="text.secondary">
              Orden: <strong>{pendingWorkflowOrden?.numero_orden_pago || "-"}</strong>
            </Typography>
            <Typography variant="body2" color="text.secondary">
              Proveedor: <strong>{pendingWorkflowOrden?.proveedores?.personas?.razon_social || "-"}</strong>
            </Typography>
            <Typography variant="body2" color="text.secondary">
              Total:{" "}
              <strong>
                {fmtMoneda(pendingWorkflowOrden?.monto_total, pendingWorkflowOrden?.moneda?.codigo || "PYG")}
              </strong>
            </Typography>
          </Box>
        )}
        confirmText={workflowConfirmType === "aprobar" ? "Sí, aprobar" : "Sí, ejecutar pago"}
        cancelText="Volver"
        confirmColor={workflowConfirmType === "aprobar" ? "success" : "primary"}
      />

      {datosMedioDialogNode}
    </Box>
  );
}

export default ComprasPagosTab;
