import { Icon } from "@iconify/react/dist/iconify.js";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { IMaskInput } from "react-imask";
import styled from "styled-components";
import {
  calcularCuotas as calcularCuotasAPI,
  getCuotasProducto,
  getPlanPorId,
} from "../../../api/planes-cuotas.service";
import { fmtFechaCalendario } from "../../../utils/fecha";
import { BancoDatalist } from "../../_standards";

/**
 * Panel de formas de pago para facturación
 * Soporta múltiples medios de pago y cálculo de cuotas según condición de pago
 *
 * Validaciones:
 * 1. Tarjetas se cargan desde referenciales
 * 2. No permite agregar pagos si total pagado >= total a pagar (contado)
 * 3. No permite que el pago supere el total a pagar (contado)
 * 4. Solo habilita pagos cuando hay items y cliente
 * 5. Contado: solo permite facturar cuando está pagado el total
 * 6. Crédito con cuota_inicial: pago inicial obligatorio, no puede igualar/superar total
 */
export function PaymentPanel({
  totalFactura = 0,
  monedaActiva = null,
  condicionPago = null,
  mediosPago = [],
  tarjetas = [],
  formasProcesamiento = [],
  planesCuotas = [],
  planesCuotasListo = false,
  items = [],
  onPagosChange,
  onCuotasChange,
  onPlanCuotaChange,
  onPrecioFinanciadoToggle,
  onValidacionChange,
  tieneItems = false,
  tieneCliente = false,
  solicitudActiva = null,
}) {
  const [pagos, setPagos] = useState([]);
  const [cuotas, setCuotas] = useState([]);
  const [planSeleccionado, setPlanSeleccionado] = useState(null);
  const [cuotasPlanElegidas, setCuotasPlanElegidas] = useState("");
  const [calculandoCuotas, setCalculandoCuotas] = useState(false);
  const [cuotasIndividuales, setCuotasIndividuales] = useState([]);

  // Sincronizar cuotas y pagos cuando se carga una solicitud de crédito.
  // Usa el cronograma persistido en la solicitud (fuente de verdad).
  const solicitudIdRef = useRef(null);
  const planHeredadoRef = useRef(null);
  useEffect(() => {
    if (!solicitudActiva || solicitudActiva.id === solicitudIdRef.current) return;
    solicitudIdRef.current = solicitudActiva.id;

    const entrega = Number(solicitudActiva.cuota_inicial_total) || 0;
    const cronograma = solicitudActiva.cronograma;

    // Usar cronograma persistido si existe
    if (Array.isArray(cronograma) && cronograma.length > 0) {
      setCuotas(cronograma.map((c) => ({
        nro_cuota: c.nro_cuota,
        monto_cuota: Number(c.monto_cuota),
        vencimiento: c.fecha_vencimiento?.split?.("T")?.[0] || c.fecha_vencimiento,
        moneda_iso: solicitudActiva.moneda || "PYG",
        saldo_pendiente: Number(c.monto_cuota),
      })));
    } else {
      // Fallback: calcular desde items si no hay cronograma
      const intervalo = solicitudActiva.intervalo_dias || 30;
      const detalles = solicitudActiva.detalle || [];
      const totalSol = Number(solicitudActiva.monto_total) || detalles.reduce((s, d) => s + Number(d.precio_total || 0), 0);
      const saldo = Number(solicitudActiva.saldo_financiar) || Math.max(0, totalSol - entrega);
      const maxC = solicitudActiva.cant_cuotas_total || detalles.reduce((m, d) => Math.max(m, Number(d.cant_cuotas) || 0), 0);

      if (maxC > 0 && saldo > 0) {
        const montoPorCuota = Math.round(saldo / maxC);
        // Parseo defensivo de "YYYY-MM-DD" a mediodía local para evitar drift de timezone
        const parseCalendario = (val) => {
          if (!val) return new Date();
          const s = String(val).slice(0, 10);
          return /^\d{4}-\d{2}-\d{2}$/.test(s) ? new Date(`${s}T12:00:00`) : new Date(val);
        };
        const fechaBase = parseCalendario(solicitudActiva.fecha_primera_cuota);
        const cuotasSol = [];
        for (let i = 1; i <= maxC; i++) {
          const fv = new Date(fechaBase);
          fv.setDate(fv.getDate() + intervalo * (i - 1));
          cuotasSol.push({
            nro_cuota: i,
            monto_cuota: i < maxC ? montoPorCuota : saldo - montoPorCuota * (maxC - 1),
            vencimiento: fv.toISOString().split("T")[0],
            moneda_iso: solicitudActiva.moneda || "PYG",
            saldo_pendiente: i < maxC ? montoPorCuota : saldo - montoPorCuota * (maxC - 1),
          });
        }
        setCuotas(cuotasSol);
      }
    }

    // La entrega inicial NO se cobra en la factura.
    // Se registra como cuota 1 en cuentas a cobrar y se cobra desde el módulo de Cobros.
  }, [solicitudActiva, mediosPago]);

  const codigoMoneda = monedaActiva?.moneda?.codigo || "PYG";
  const simboloMoneda = monedaActiva?.moneda?.simbolo || "₲";

  // Determinar si es contado o crédito
  const esCredito = condicionPago?.cod_condicion_venta === 2;
  const esCuotas = condicionPago?.cod_tipo_credito === 2;
  const requiereCuotaInicial = condicionPago?.cuota_inicial === true;
  const cantidadCuotas = condicionPago?.cuotas || 1;
  const intervaloDias = condicionPago?.intervalo_dias || 30;
  const diasPlazo = condicionPago?.dias_plazo || 0;

  // Calcular total pagado
  const totalPagado = pagos.reduce((sum, p) => sum + (p.monto_pago || 0), 0);
  const saldoPendiente = totalFactura - totalPagado;
  const vuelto =
    !esCredito && totalPagado > totalFactura ? totalPagado - totalFactura : 0;

  // "Total a pagar" mostrado al vendedor: en crédito con cuotas, el cliente termina
  // pagando entrega inicial + cuotas (capital + interés de financiación), no solo el
  // total de la factura (que es la base de venta/IVA y no incluye el interés). Ver
  // docs/info/aclaracion-gastos-cuotas.md.
  const totalAPagarReal =
    esCredito && cuotas.length > 0
      ? totalPagado + cuotas.reduce((sum, c) => sum + Number(c.monto_cuota || 0), 0)
      : totalFactura;

  // Validaciones
  const panelHabilitado = tieneItems && tieneCliente && totalFactura > 0;
  const puedeAgregarPago = useMemo(() => {
    if (!panelHabilitado) return false;
    if (!esCredito) {
      // Contado: puede agregar si no ha pagado todo
      return totalPagado < totalFactura;
    } else if (requiereCuotaInicial) {
      // Crédito con cuota inicial: solo un pago inicial que no iguale/supere el total
      return pagos.length === 0;
    }
    // Crédito sin cuota inicial: no requiere pagos
    return false;
  }, [
    panelHabilitado,
    esCredito,
    totalPagado,
    totalFactura,
    requiereCuotaInicial,
    pagos.length,
  ]);

  // Validación para permitir facturar
  const validacionPago = useMemo(() => {
    if (!panelHabilitado) {
      return { valido: false, mensaje: "Agregue items y cliente" };
    }

    if (!esCredito) {
      // Contado: debe estar pagado el total exacto (no más, no menos)
      if (totalPagado < totalFactura) {
        return {
          valido: false,
          mensaje: "Debe pagar el total para facturar al contado",
        };
      }
      if (totalPagado > totalFactura) {
        return {
          valido: false,
          mensaje: "El total pagado supera el monto a pagar",
        };
      }
      return { valido: true, mensaje: "" };
    } else if (requiereCuotaInicial && !solicitudActiva) {
      // Crédito con cuota inicial obligatoria (sin solicitud)
      if (pagos.length === 0) {
        return { valido: false, mensaje: "Debe registrar un pago inicial" };
      }
      if (totalPagado >= totalFactura) {
        return {
          valido: false,
          mensaje: "El pago inicial no puede igualar o superar el total",
        };
      }
      return { valido: true, mensaje: "" };
    }
    // Validar campos obligatorios de cheque
    for (const pago of pagos) {
      if (esCheque(pago.medio_pago_id)) {
        if (!pago.numero_cheque?.trim() || pago.numero_cheque.trim().length !== 8)
          return { valido: false, mensaje: "El número de cheque debe tener 8 caracteres" };
        if (!pago.banco_emisor?.trim() || pago.banco_emisor.trim().length < 4 || pago.banco_emisor.trim().length > 20)
          return { valido: false, mensaje: "El banco emisor debe tener entre 4 y 20 caracteres" };
      }
    }

    // Crédito sin cuota inicial, o con solicitud activa (entrega se cobra en Cobros): siempre válido
    return { valido: true, mensaje: "" };
  }, [
    panelHabilitado,
    esCredito,
    requiereCuotaInicial,
    pagos,
    totalPagado,
    totalFactura,
  ]);

  // Saldo para cuotas (total - pago inicial en crédito)
  const saldoParaCuotas = esCredito ? totalFactura - totalPagado : 0;

  // Formatear monto
  const formatMonto = (valor) => {
    const num = valor || 0;
    let decimales = 0;
    if (codigoMoneda !== "PYG") {
      decimales = monedaActiva?.decimales_visualizar ?? 2;
    }
    return `${simboloMoneda} ${num.toLocaleString("es-PY", {
      minimumFractionDigits: decimales,
      maximumFractionDigits: decimales,
    })}`;
  };

  // Resetear plan cuando cambia la condición de pago
  useEffect(() => {
    setPlanSeleccionado(null);
  }, [condicionPago?.id]);

  // Calcular cuotas localmente (fallback sin plan)
  const generarCuotasLocal = useCallback(() => {
    if (!esCredito || saldoParaCuotas <= 0) return [];

    const nuevasCuotas = [];
    const fechaBase = new Date();

    if (esCuotas) {
      const montoCuota =
        Math.round((saldoParaCuotas / cantidadCuotas) * 100) / 100;

      for (let i = 0; i < cantidadCuotas; i++) {
        const fechaVencimiento = new Date(fechaBase);
        fechaVencimiento.setDate(
          fechaVencimiento.getDate() + intervaloDias * (i + 1),
        );

        nuevasCuotas.push({
          nro_cuota: i + 1,
          monto_cuota:
            i === cantidadCuotas - 1
              ? saldoParaCuotas - montoCuota * (cantidadCuotas - 1)
              : montoCuota,
          vencimiento: fechaVencimiento.toISOString().split("T")[0],
          moneda_iso: codigoMoneda,
          saldo_pendiente:
            i === cantidadCuotas - 1
              ? saldoParaCuotas - montoCuota * (cantidadCuotas - 1)
              : montoCuota,
        });
      }
    } else {
      const fechaVencimiento = new Date(fechaBase);
      fechaVencimiento.setDate(fechaVencimiento.getDate() + diasPlazo);

      nuevasCuotas.push({
        nro_cuota: 1,
        monto_cuota: saldoParaCuotas,
        vencimiento: fechaVencimiento.toISOString().split("T")[0],
        moneda_iso: codigoMoneda,
        saldo_pendiente: saldoParaCuotas,
      });
    }
    return nuevasCuotas;
  }, [
    esCredito,
    esCuotas,
    cantidadCuotas,
    intervaloDias,
    diasPlazo,
    saldoParaCuotas,
    codigoMoneda,
  ]);

  // Generar cuotas: usar API del plan si hay plan seleccionado, sino cálculo local.
  // Si hay solicitud activa, las cuotas vienen precargadas — no recalcular.
  useEffect(() => {
    if (solicitudActiva) return;

    if (!esCredito || saldoParaCuotas <= 0) {
      setCuotas([]);
      return;
    }

    // Si hay un plan seleccionado y es tipo cuotas, usar API
    if (esCuotas && planSeleccionado) {
      setCalculandoCuotas(true);
      calcularCuotasAPI({
        planCuotaId: planSeleccionado.id,
        montoTotal: saldoParaCuotas,
        monedaIso: codigoMoneda,
        cantidadCuotas: cuotasPlanElegidas ? Number(cuotasPlanElegidas) : undefined,
      })
        .then((response) => {
          const resultado = response?.data;
          if (resultado?.cuotas_calculadas_detalle) {
            const cuotasAPI = resultado.cuotas_calculadas_detalle.map((d) => ({
              nro_cuota: d.numero_cuota,
              monto_cuota: Number(d.monto_cuota),
              vencimiento:
                d.fecha_vencimiento?.split?.("T")?.[0] || d.fecha_vencimiento,
              moneda_iso: codigoMoneda,
              saldo_pendiente: Number(d.monto_cuota),
            }));
            setCuotas(cuotasAPI);
          } else {
            setCuotas(generarCuotasLocal());
          }
        })
        .catch(() => {
          setCuotas(generarCuotasLocal());
        })
        .finally(() => setCalculandoCuotas(false));
    } else {
      // Sin plan: cálculo local
      setCuotas(generarCuotasLocal());
    }
  }, [
    esCredito,
    esCuotas,
    saldoParaCuotas,
    totalFactura,
    codigoMoneda,
    planSeleccionado,
    cuotasPlanElegidas,
    generarCuotasLocal,
    solicitudActiva,
  ]);

  // Resetear pagos cuando se limpia el formulario (totalFactura = 0 o no hay items/cliente)
  useEffect(() => {
    if (totalFactura === 0 || !tieneItems || !tieneCliente) {
      setPagos([]);
      setCuotas([]);
      setPlanSeleccionado(null);
    }
  }, [totalFactura, tieneItems, tieneCliente]);

  // Notificar cambios
  useEffect(() => {
    onPagosChange?.(pagos);
  }, [pagos, onPagosChange]);

  useEffect(() => {
    onCuotasChange?.(cuotas);
  }, [cuotas, onCuotasChange]);

  useEffect(() => {
    onPlanCuotaChange?.(planSeleccionado);
  }, [planSeleccionado, onPlanCuotaChange]);

  // Fase 7: al cargar una solicitud de crédito que ya tenía un plan automático
  // asignado, preseleccionarlo — si no, la factura resultante pierde la
  // trazabilidad (`plan_cuota_id` quedaría null aunque la solicitud sí tenía uno).
  // Pide el plan directo por id (no busca en `planesCuotas`): desde el Step 2 de
  // esta task, `planesCuotas` viene filtrado por el carrito actual vía
  // `obtenerPlanesAplicables`, así que el plan original de la solicitud puede no
  // aparecer ahí (fue desactivado, o el carrito ya no matchea su alcance) y el
  // efecto reintentaría para siempre sin encontrarlo nunca.
  useEffect(() => {
    if (!solicitudActiva?.plan_cuota_id) return;
    if (planHeredadoRef.current === solicitudActiva.id) return;
    planHeredadoRef.current = solicitudActiva.id;
    getPlanPorId(solicitudActiva.plan_cuota_id)
      .then((resp) => {
        const plan = resp?.data;
        if (plan) setPlanSeleccionado(plan);
      })
      .catch(() => {
        // Plan no encontrado o sin acceso — no rompe el flujo, el usuario puede elegir a mano.
      });
  }, [solicitudActiva]);

  // Fase 7 (fix revisión final, Important 1): si el carrito cambia y el plan
  // seleccionado deja de aplicar (cambio de categoría/precio), `planesCuotas`
  // se refetchea sin ese plan — hay que limpiar la selección para no seguir
  // calculando cuotas y enviando `plan_cuota_id` de un plan que ya no matchea.
  // Guards:
  // - `planesCuotasListo` evita limpiar durante la ventana en que la query está
  //   en fetch (queryKey nueva -> `planesCuotas` momentáneamente `[]`).
  // - Si hay solicitud activa, el plan puede venir heredado (`getPlanPorId` más
  //   arriba) y es intencional que no esté en la lista filtrada por el carrito.
  useEffect(() => {
    if (solicitudActiva) return;
    if (!planesCuotasListo) return;
    if (!planSeleccionado) return;
    const sigueValido = planesCuotas.some((p) => p.id === planSeleccionado.id);
    if (!sigueValido) {
      setPlanSeleccionado(null);
      setCuotasPlanElegidas("");
    }
  }, [planesCuotas, planesCuotasListo, planSeleccionado, solicitudActiva]);

  // Buscar cuotas individuales por producto cuando es tipo cuotas y hay items
  // Auto-aplicar precio financiado cuando se encuentran
  useEffect(() => {
    // Plan automático y cuotas por producto son excluyentes: el plan financia el
    // TOTAL del carrito con su propio interés, y las cuotas por producto ya traen
    // el precio financiado incorporado — aplicar ambos cobraría interés sobre un
    // precio ya financiado. Con un plan activo se revierte cualquier precio
    // financiado por producto y se factura a precio de catálogo.
    // (Antes esto ocurría de casualidad: el filtro comparaba contra
    // `c.plan_cuota_id`, columna que `producto_precio_cuota` no tiene, así que
    // nunca matcheaba. Ahora es explícito.)
    if (!esCuotas || items.length === 0 || planSeleccionado) {
      // Revertir precios financiados de productos que los tenían
      cuotasIndividuales.forEach((ci) => {
        onPrecioFinanciadoToggle?.(ci.producto_id, 0, false);
      });
      setCuotasIndividuales([]);
      return;
    }

    const productIds = [
      ...new Set(items.map((it) => it.producto_id).filter(Boolean)),
    ];
    if (productIds.length === 0) {
      setCuotasIndividuales([]);
      return;
    }

    let cancelled = false;
    Promise.all(
      productIds.map((pid) =>
        getCuotasProducto(pid)
          .then((res) => {
            const cuotasData = res?.data || [];
            // Sin plan automático (garantizado por el early-return de arriba):
            // se ofrecen todas las cuotas activas del producto.
            const matches = cuotasData.filter((c) => c.activo);

            const item = items.find((it) => it.producto_id === pid);
            return matches.map((match) => ({
              ...match,
              producto_id: pid,
              producto_nombre: item?.descripcion || item?.nombre || "Producto",
              cantidad: item?.cantidad || 1,
            }));
          })
          .catch(() => []),
      ),
    ).then((results) => {
      if (!cancelled) {
        const found = results.flat().filter(Boolean);
        setCuotasIndividuales(found);

        // Auto-aplicar precio financiado para cada producto con cuota individual
        found.forEach((ci) => {
          const precioFinanciado = Number(ci.monto_cuota) * ci.cantidad_cuotas;
          onPrecioFinanciadoToggle?.(ci.producto_id, precioFinanciado, true);
        });
      }
    });

    return () => {
      cancelled = true;
    };
  }, [esCuotas, planSeleccionado, items.length]); // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    onValidacionChange?.(validacionPago);
  }, [validacionPago, onValidacionChange]);

  // Agregar forma de pago
  const handleAddPago = () => {
    if (!puedeAgregarPago) return;
    const medioPagoDefault =
      mediosPago.find((m) => m.codigo === 1) || mediosPago[0];

    setPagos([
      ...pagos,
      {
        id: Date.now(),
        medio_pago_id: medioPagoDefault?.id || "",
        moneda_id: monedaActiva?.moneda_id || "",
        monto_pago: saldoPendiente > 0 ? saldoPendiente : 0,
        // Campos opcionales para tarjeta
        tarjeta_id: null,
        forma_procesamiento_pago_id: null,
        nombre_titular_tarjeta: "",
        numero_tarjeta: "",
        // Campos opcionales para cheque
        numero_cheque: "",
        banco_emisor: "",
      },
    ]);
  };

  // Obtener medio de pago por ID
  const getMedioPago = (id) => mediosPago.find((m) => m.id === id);

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

  const esMedioTarjeta = (medio) => {
    if (!medio) return false;
    const codigo = Number(medio.codigo);
    const descripcion = normalizarTexto(medio.descripcion);
    if (descripcion.includes("tarjeta")) return true;
    // Catálogos donde débito/crédito puede venir como 3 o 4.
    return codigo === 3 || codigo === 4;
  };

  const esMedioCheque = (medio) => {
    if (!medio) return false;
    return Number(medio.codigo) === 2;
  };

  // Actualizar forma de pago
  const handleUpdatePago = (id, field, value) => {
    setPagos((prev) =>
      prev.map((p) => {
        if (p.id !== id) return p;

        const next = { ...p, [field]: value };
        if (field !== "medio_pago_id") return next;

        const medio = getMedioPago(value);
        const isTarjeta = esMedioTarjeta(medio);
        const isCheque = esMedioCheque(medio);

        // Limpiar campos no aplicables al tipo elegido.
        if (!isTarjeta) {
          next.tarjeta_id = null;
          next.forma_procesamiento_pago_id = null;
          next.nombre_titular_tarjeta = "";
          next.numero_tarjeta = "";
        }
        if (!isCheque) {
          next.numero_cheque = "";
          next.banco_emisor = "";
        }

        return next;
      }),
    );
  };

  // Eliminar forma de pago
  const handleRemovePago = (id) => {
    setPagos(pagos.filter((p) => p.id !== id));
  };

  // Verificar si el medio requiere datos de tarjeta
  const requiereTarjeta = (medioPagoId) => {
    const medio = getMedioPago(medioPagoId);
    return esMedioTarjeta(medio);
  };

  // Verificar si el medio es cheque
  const esCheque = (medioPagoId) => {
    const medio = getMedioPago(medioPagoId);
    return esMedioCheque(medio);
  };

  return (
    <Container>
      <Header>
        <h3>
          <Icon icon="mdi:credit-card-outline" />
          Forma de Pago
        </h3>
        {condicionPago && (
          <CondicionBadge $credito={esCredito}>
            {condicionPago.descripcion}
          </CondicionBadge>
        )}
      </Header>

      {/* Resumen de pago */}
      <ResumenPago>
        <div className="row">
          <span>Total a pagar:</span>
          <strong>{formatMonto(totalAPagarReal)}</strong>
        </div>
        {esCredito && cuotas.length > 0 && totalAPagarReal !== totalFactura && (
          <div className="row">
            <span>(Venta {formatMonto(totalFactura)} + interés {formatMonto(totalAPagarReal - totalFactura)})</span>
          </div>
        )}
        {pagos.length > 0 && (
          <>
            <div className="row">
              <span>Total pagado:</span>
              <span className="pagado">{formatMonto(totalPagado)}</span>
            </div>
            {saldoPendiente > 0 && (
              <div className="row">
                <span>Saldo pendiente:</span>
                <span className="pendiente">{formatMonto(saldoPendiente)}</span>
              </div>
            )}
            {vuelto > 0 && (
              <div className="row">
                <span className="exceso-label">⚠ Excede total:</span>
                <span className="exceso">{formatMonto(vuelto)}</span>
              </div>
            )}
          </>
        )}
      </ResumenPago>

      {/* Mensaje de validación */}
      {!validacionPago.valido && validacionPago.mensaje && panelHabilitado && (
        <ValidationMessage>
          <Icon icon="mdi:alert-circle-outline" />
          <span>{validacionPago.mensaje}</span>
        </ValidationMessage>
      )}

      {/* Panel deshabilitado */}
      {!panelHabilitado && (
        <DisabledMessage>
          <Icon icon="mdi:information-outline" />
          <span>Agregue items y cliente para registrar pagos</span>
        </DisabledMessage>
      )}

      {/* Lista de pagos (contado, o pago inicial de crédito sin solicitud) */}
      {panelHabilitado && (!esCredito || (requiereCuotaInicial && !solicitudActiva)) && (
        <PagosSection>
          <SectionHeader>
            <span>
              {requiereCuotaInicial ? "Pago Inicial" : "Medios de Pago"}
            </span>
            <button
              type="button"
              onClick={handleAddPago}
              disabled={!puedeAgregarPago}
            >
              <Icon icon="mdi:plus" /> Agregar
            </button>
          </SectionHeader>

          {pagos.length === 0 ? (
            <EmptyState>
              <Icon icon="mdi:cash-register" />
              <p>
                {requiereCuotaInicial
                  ? "Agregue el pago inicial"
                  : "Agregue un medio de pago"}
              </p>
            </EmptyState>
          ) : (
            <PagosList>
              {pagos.map((pago) => (
                <PagoItem key={pago.id}>
                  <div className="pago-header">
                    <select
                      value={pago.medio_pago_id}
                      onChange={(e) =>
                        handleUpdatePago(
                          pago.id,
                          "medio_pago_id",
                          e.target.value,
                        )
                      }
                    >
                      <option value="">Seleccionar medio</option>
                      {mediosPago.map((m) => (
                        <option key={m.id} value={m.id}>
                          {m.descripcion}
                        </option>
                      ))}
                    </select>
                    <button
                      type="button"
                      className="remove-btn"
                      onClick={() => handleRemovePago(pago.id)}
                    >
                      <Icon icon="mdi:close" />
                    </button>
                  </div>

                  <div className="pago-monto">
                    <label>Monto:</label>
                    <div className={`input-group${!esCredito && totalPagado > totalFactura ? " input-error" : ""}`}>
                      <span className="symbol">{simboloMoneda}</span>
                      <IMaskInput
                        mask={Number}
                        scale={codigoMoneda !== "PYG" ? (monedaActiva?.decimales_visualizar ?? 2) : 0}
                        signed={false}
                        thousandsSeparator="."
                        radix=","
                        mapToRadix={["."]}
                        min={0}
                        max={!esCredito ? totalFactura - (totalPagado - (pago.monto_pago || 0)) : undefined}
                        unmask={true}
                        value={String(pago.monto_pago ?? 0)}
                        onAccept={(val) =>
                          handleUpdatePago(pago.id, "monto_pago", Number(val) || 0)
                        }
                      />
                    </div>
                  </div>

                  {/* Campos adicionales para tarjeta */}
                  {requiereTarjeta(pago.medio_pago_id) && (
                    <div className="pago-extra">
                      <select
                        value={pago.tarjeta_id || ""}
                        onChange={(e) =>
                          handleUpdatePago(
                            pago.id,
                            "tarjeta_id",
                            e.target.value,
                          )
                        }
                      >
                        <option value="">Seleccionar tarjeta</option>
                        {tarjetas.map((t) => (
                          <option key={t.id} value={t.id}>
                            {t.descripcion}
                          </option>
                        ))}
                      </select>
                      <input
                        type="text"
                        placeholder="Últimos 4 dígitos"
                        maxLength={4}
                        value={pago.numero_tarjeta || ""}
                        onChange={(e) =>
                          handleUpdatePago(
                            pago.id,
                            "numero_tarjeta",
                            e.target.value,
                          )
                        }
                      />
                    </div>
                  )}

                  {/* Campos adicionales para cheque */}
                  {esCheque(pago.medio_pago_id) && (
                    <div className="pago-extra">
                      <input
                        type="text"
                        placeholder="Nro. Cheque"
                        maxLength={8}
                        value={pago.numero_cheque || ""}
                        onChange={(e) =>
                          handleUpdatePago(
                            pago.id,
                            "numero_cheque",
                            e.target.value,
                          )
                        }
                      />
                      {/* Este banco viaja a SIFEN (dBcoEmi) y está limitado a
                          20 caracteres, por eso el datalist ofrece los nombres
                          cortos del catálogo y no los completos. */}
                      <input
                        type="text"
                        list="bancos-pos"
                        placeholder="Banco emisor"
                        maxLength={20}
                        value={pago.banco_emisor || ""}
                        onChange={(e) =>
                          handleUpdatePago(
                            pago.id,
                            "banco_emisor",
                            e.target.value,
                          )
                        }
                      />
                      <BancoDatalist id="bancos-pos" />
                    </div>
                  )}
                </PagoItem>
              ))}
            </PagosList>
          )}
        </PagosSection>
      )}

      {/* Plan de Cuotas Automático (addon) — si la empresa no tiene el addon contratado,
          `planesCuotas` llega vacío y esta sección no se muestra; sin plan seleccionado
          se sigue usando el cálculo simple sin interés de siempre. */}
      {esCredito && esCuotas && !solicitudActiva && planesCuotas.length > 0 && (
        <PlanSelector>
          <label htmlFor="plan-cuotas-select">
            <Icon icon="mdi:calculator" />
            Plan de cuotas automático
          </label>
          <select
            id="plan-cuotas-select"
            value={planSeleccionado?.id || ""}
            onChange={(e) => {
              const plan = planesCuotas.find((p) => p.id === e.target.value);
              setPlanSeleccionado(plan || null);
              setCuotasPlanElegidas(plan?.cantidad_cuotas || "");
            }}
          >
            <option value="">Sin plan (división simple, sin interés)</option>
            {planesCuotas.map((plan) => (
              <option key={plan.id} value={plan.id}>
                {plan.nombre}
                {Number(plan.tasa_interes) > 0 ? ` (${Number(plan.tasa_interes)}% ${plan.tipo_interes})` : " (sin interés)"}
              </option>
            ))}
          </select>
          {planSeleccionado && (
            <>
              <label htmlFor="plan-cuotas-cantidad" style={{ marginTop: 8 }}>
                Cantidad de cuotas (máx. {planSeleccionado.cantidad_cuotas})
              </label>
              <input
                id="plan-cuotas-cantidad"
                type="number"
                min={1}
                max={planSeleccionado.cantidad_cuotas}
                value={cuotasPlanElegidas}
                onChange={(e) => {
                  const v = Math.max(1, Math.min(planSeleccionado.cantidad_cuotas, Number(e.target.value) || 1));
                  setCuotasPlanElegidas(v);
                }}
              />
              <span className="plan-info">
                cada {planSeleccionado.intervalo_dias} días
              </span>
            </>
          )}
        </PlanSelector>
      )}

      {/* Cuotas (para crédito con cuotas o plazo) */}
      {esCredito && (cuotas.length > 0 || calculandoCuotas) && (
        <CuotasSection>
          <SectionHeader>
            <span>
              {calculandoCuotas
                ? "Calculando cuotas..."
                : solicitudActiva
                  ? (() => {
                      const int = solicitudActiva.intervalo_dias || 30;
                      const freq = int === 7 ? "semanal" : int === 15 ? "quincenal" : int === 30 ? "mensual" : `cada ${int} días`;
                      return `Cuenta a Cobrar — ${freq} (${cuotas.length} cuotas)`;
                    })()
                  : esCuotas
                    ? planSeleccionado
                      ? `${planSeleccionado.nombre} (${cuotas.length} cuotas)`
                      : `Plan de Cuotas (${cantidadCuotas} cuotas)`
                    : `Cuenta a Cobrar (${diasPlazo} días)`}
            </span>
          </SectionHeader>
          {calculandoCuotas ? (
            <EmptyState>
              <Icon icon="mdi:loading" className="spin" />
              <p>Calculando cuotas con el plan...</p>
            </EmptyState>
          ) : (
            <CuotasList>
              {cuotas.map((cuota) => (
                <CuotaItem key={cuota.nro_cuota}>
                  <span className="nro">
                    {esCuotas ? `Cuota ${cuota.nro_cuota}` : "Vencimiento"}
                  </span>
                  <span className="vencimiento">
                    {fmtFechaCalendario(cuota.vencimiento, "-")}
                  </span>
                  <span className="monto">
                    {formatMonto(cuota.monto_cuota)}
                  </span>
                </CuotaItem>
              ))}
            </CuotasList>
          )}
        </CuotasSection>
      )}

      {/* Cuotas individuales por producto (informativo) */}
      {esCuotas && cuotasIndividuales.length > 0 && (
        <CuotasIndividualesSection>
          <SectionHeader>
            <span>
              <Icon
                icon="mdi:tag-multiple-outline"
                style={{ marginRight: 4, verticalAlign: "middle" }}
              />
              Precios de cuota aplicados
            </span>
          </SectionHeader>
          <CuotasList>
            {cuotasIndividuales.map((ci) => {
              const precioFinanciado =
                Number(ci.monto_cuota) * ci.cantidad_cuotas;

              return (
                <CuotaIndividualItem key={ci.id}>
                  <div className="producto-info">
                    <span className="nombre">{ci.producto_nombre}</span>
                    <span className="detalle">
                      {ci.cantidad_cuotas} cuotas de{" "}
                      {formatMonto(Number(ci.monto_cuota))}
                    </span>
                    <span className="activo-label">
                      Precio financiado: {formatMonto(precioFinanciado)}
                    </span>
                  </div>
                  <div className="totales">
                    <span className="total-cuotas">
                      Total: {formatMonto(precioFinanciado * ci.cantidad)}
                    </span>
                    {ci.cuota_inicial && Number(ci.cuota_inicial) > 0 && (
                      <span className="entrada">
                        Entrada: {formatMonto(Number(ci.cuota_inicial))}
                      </span>
                    )}
                  </div>
                </CuotaIndividualItem>
              );
            })}
          </CuotasList>
        </CuotasIndividualesSection>
      )}
    </Container>
  );
}

const Container = styled.div`
  background: ${({ theme }) => theme.bg2};
  border-radius: 12px;
  border: 1px solid ${({ theme }) => theme.color2};
  overflow: hidden;
`;

const Header = styled.div`
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  background: ${({ theme }) => theme.bg3};
  border-bottom: 1px solid ${({ theme }) => theme.color2};

  h3 {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    font-size: 0.95rem;
    font-weight: 600;
    color: ${({ theme }) => theme.text};
  }
`;

const CondicionBadge = styled.span`
  padding: 4px 10px;
  border-radius: 12px;
  font-size: 0.75rem;
  font-weight: 500;
  background: ${({ $credito }) => ($credito ? "#ff980020" : "#4caf5020")};
  color: ${({ $credito }) => ($credito ? "#ff9800" : "#4caf50")};
`;

const ValidationMessage = styled.div`
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  background: #ff980015;
  border-bottom: 1px solid #ff980030;
  color: #ff9800;
  font-size: 0.8rem;

  svg {
    font-size: 1rem;
    flex-shrink: 0;
  }
`;

const DisabledMessage = styled.div`
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  background: ${({ theme }) => theme.bg3};
  border-bottom: 1px solid ${({ theme }) => theme.color2};
  color: ${({ theme }) => theme.textSecondary};
  font-size: 0.8rem;

  svg {
    font-size: 1rem;
    flex-shrink: 0;
  }
`;

const ResumenPago = styled.div`
  padding: 12px 16px;
  border-bottom: 1px solid ${({ theme }) => theme.color2};

  .row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 4px 0;
    font-size: 0.85rem;

    span {
      color: ${({ theme }) => theme.textSecondary};
    }

    strong {
      color: ${({ theme }) => theme.text};
      font-size: 1rem;
    }

    .pagado {
      color: #4caf50;
    }

    .pendiente {
      color: #ff9800;
    }

    .vuelto {
      color: #2196f3;
      font-weight: 600;
    }

    .exceso-label {
      color: #dc3545;
      font-weight: 600;
    }

    .exceso {
      color: #dc3545;
      font-weight: 700;
    }
  }
`;

const PagosSection = styled.div`
  padding: 12px 16px;
`;

const SectionHeader = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;

  span {
    font-size: 0.8rem;
    font-weight: 500;
    color: ${({ theme }) => theme.textSecondary};
    text-transform: uppercase;
    letter-spacing: 0.5px;
  }

  button {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 6px 12px;
    border: none;
    border-radius: 6px;
    background: ${({ theme }) => theme.primary};
    color: #fff;
    font-size: 0.8rem;
    cursor: pointer;
    transition:
      opacity 0.2s,
      background 0.2s;

    &:disabled {
      background: ${({ theme }) => theme.color2};
      color: ${({ theme }) => theme.textSecondary};
      cursor: not-allowed;
      opacity: 0.6;
    }

    &:hover {
      opacity: 0.9;
    }
  }
`;

const EmptyState = styled.div`
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 24px;
  color: ${({ theme }) => theme.textSecondary};

  svg {
    font-size: 2rem;
    margin-bottom: 8px;
    opacity: 0.5;
  }

  p {
    margin: 0;
    font-size: 0.85rem;
  }
`;

const PagosList = styled.div`
  display: flex;
  flex-direction: column;
  gap: 12px;
`;

const PagoItem = styled.div`
  background: ${({ theme }) => theme.bg3};
  border-radius: 8px;
  padding: 12px;
  overflow: hidden;

  .pago-header {
    display: flex;
    gap: 8px;
    margin-bottom: 10px;

    select {
      flex: 1;
      padding: 8px 12px;
      border: 1px solid ${({ theme }) => theme.color2};
      border-radius: 6px;
      background: ${({ theme }) => theme.bg2};
      color: ${({ theme }) => theme.text};
      font-size: 0.85rem;
    }

    .remove-btn {
      padding: 8px;
      border: none;
      border-radius: 6px;
      background: #f4433620;
      color: #f44336;
      cursor: pointer;
      transition: background 0.2s;

      &:hover {
        background: #f4433640;
      }
    }
  }

  .pago-monto {
    display: flex;
    align-items: center;
    gap: 8px;

    label {
      font-size: 0.8rem;
      color: ${({ theme }) => theme.textSecondary};
    }

    .input-group {
      flex: 1;
      display: flex;
      align-items: center;
      background: ${({ theme }) => theme.bg2};
      border: 1px solid ${({ theme }) => theme.color2};
      border-radius: 6px;
      overflow: hidden;

      .symbol {
        padding: 8px 12px;
        background: ${({ theme }) => theme.bg3};
        color: ${({ theme }) => theme.textSecondary};
        font-size: 0.85rem;
      }

      input {
        flex: 1;
        padding: 8px 12px;
        border: none;
        background: transparent;
        color: ${({ theme }) => theme.text};
        font-size: 0.9rem;
        text-align: right;

        &:focus {
          outline: none;
        }
      }

      &.input-error {
        border-color: #dc3545;
        box-shadow: 0 0 0 2px rgba(220, 53, 69, 0.2);
      }
    }
  }

  .pago-extra {
    display: flex;
    gap: 8px;
    margin-top: 10px;

    select,
    input {
      flex: 1;
      min-width: 0;
      padding: 8px 12px;
      border: 1px solid ${({ theme }) => theme.color2};
      border-radius: 6px;
      background: ${({ theme }) => theme.bg2};
      color: ${({ theme }) => theme.text};
      font-size: 0.8rem;

      &::placeholder {
        color: ${({ theme }) => theme.textSecondary};
      }
    }
  }
`;

const PlanSelector = styled.div`
  padding: 12px 16px;
  border-top: 1px solid ${({ theme }) => theme.color2};

  label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.8rem;
    font-weight: 500;
    color: ${({ theme }) => theme.textSecondary};
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 8px;

    svg {
      font-size: 1rem;
    }
  }

  select,
  input[type="number"] {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid ${({ theme }) => theme.color2};
    border-radius: 6px;
    background: ${({ theme }) => theme.bg3};
    color: ${({ theme }) => theme.text};
    font-size: 0.85rem;
    cursor: pointer;

    &:focus {
      outline: none;
      border-color: ${({ theme }) => theme.primary};
    }
  }

  input[type="number"] {
    cursor: text;
  }

  .plan-info {
    display: block;
    margin-top: 6px;
    font-size: 0.75rem;
    color: ${({ theme }) => theme.textSecondary};
  }
`;

const CuotasSection = styled.div`
  padding: 12px 16px;
  border-top: 1px solid ${({ theme }) => theme.color2};
`;

const CuotasList = styled.div`
  display: flex;
  flex-direction: column;
  gap: 6px;
`;

const CuotaItem = styled.div`
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  background: ${({ theme }) => theme.bg3};
  border-radius: 6px;
  font-size: 0.85rem;

  .nro {
    font-weight: 500;
    color: ${({ theme }) => theme.text};
  }

  .vencimiento {
    color: ${({ theme }) => theme.textSecondary};
  }

  .monto {
    font-weight: 600;
    color: ${({ theme }) => theme.primary};
  }
`;

const CuotasIndividualesSection = styled.div`
  padding: 12px 16px;
  border-top: 1px dashed ${({ theme }) => theme.color2};
  background: ${({ theme }) => theme.bg2};
`;

const CuotaIndividualItem = styled.div`
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: #4caf5010;
  border-radius: 6px;
  border-left: 3px solid #4caf50;

  .producto-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1;
    min-width: 0;

    .nombre {
      font-weight: 500;
      font-size: 0.85rem;
      color: ${({ theme }) => theme.text};
    }

    .detalle {
      font-size: 0.75rem;
      color: ${({ theme }) => theme.textSecondary};
    }

    .activo-label {
      font-size: 0.7rem;
      font-weight: 600;
      color: #4caf50;
    }
  }

  .totales {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 2px;
    flex-shrink: 0;

    .total-cuotas {
      font-weight: 600;
      font-size: 0.85rem;
      color: #4caf50;
    }

    .entrada {
      font-size: 0.75rem;
      color: ${({ theme }) => theme.textSecondary};
    }
  }
`;
