import { Icon } from "@iconify/react";
import { Alert, AlertTitle, Box, Button, IconButton, Stack, Tooltip, Typography } from "@mui/material";
import { useEffect, useMemo, useState } from "react";
import { toast } from "sonner";
import {
  anularAcreditacionBancaria,
  confirmarAcreditacionBancaria,
  descargarAcreditacionBancaria,
  enviarAcreditacionBancaria,
  generarAcreditacionBancaria,
  getAcreditacionBancaria,
  getAcreditacionesBancarias,
  getBancosRrhh,
  getFormatosBancarios,
  getLiquidaciones,
} from "../../api/rrhh.service";
import { getTesCuentas } from "../../api/tes.service";
import { useConfirmDialog } from "../../hooks/useConfirmDialog";
import {
  Badge,
  Container,
  Divider,
  EmptyState,
  Field,
  FieldsGrid,
  Footer,
  FooterActionButton,
  FormHead,
  FormPanel,
  GhostButton,
  ListBody,
  ListPanel,
  RowActions,
  SectionTitle,
  TableWrap,
  ToolBar,
} from "../ui/FormShell";
import { TablePaginationBar } from "../_standards";
import { SearchableSelect } from "../ui/SearchableSelect";
import { useRRHHContext } from "./_shared/RRHHContext";
import { RRHHGuia } from "./_shared/RRHHGuia";
import { RRHHPrereqChecklist } from "./_shared/RRHHPrereqChecklist";
import { RRHHEmptyState } from "./_shared/RRHHEmptyState";

const ESTADO_OPTIONS = [
  { id: "GENERADO", label: "Generado" },
  { id: "ENVIADO", label: "Enviado al banco" },
  { id: "CONFIRMADO", label: "Confirmado" },
  { id: "ANULADO", label: "Anulado" },
];

const fmtMonto = (v) => Number(v || 0).toLocaleString("es-PY");
const fmtFecha = (v) => {
  if (!v) return "—";
  const d = new Date(v);
  return Number.isNaN(d.getTime()) ? "—" : d.toLocaleDateString("es-PY");
};
const fmtFechaHora = (v) => {
  if (!v) return "—";
  const d = new Date(v);
  return Number.isNaN(d.getTime()) ? "—" : d.toLocaleString("es-PY");
};
const fmtPeriodo = (liq) => {
  if (!liq) return "—";
  const base = `${String(liq.periodo_mes).padStart(2, "0")}/${liq.periodo_anio}`;
  if (liq.tipo === "QUINCENAL") return `${base} · Q${liq.quincena}`;
  return base;
};

export function AcreditacionesBancariasTab() {
  const { confirm, prompt, dialogs } = useConfirmDialog();
  const { setActiveTab } = useRRHHContext();

  const [data, setData] = useState([]);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(1);
  const [limit, setLimit] = useState(20);
  const [estadoFiltro, setEstadoFiltro] = useState("");
  const [bancoFiltro, setBancoFiltro] = useState("");
  const [loading, setLoading] = useState(false);

  const [bancos, setBancos] = useState([]);
  const [formatos, setFormatos] = useState([]);
  const [liquidacionesCerradas, setLiquidacionesCerradas] = useState([]);
  const [acreditacionesConfirmadas, setAcreditacionesConfirmadas] = useState([]);
  // Cuentas de tesorería (vacío si la empresa no usa el módulo Tesorería).
  const [tesCuentas, setTesCuentas] = useState([]);

  // Wizard
  const [showGen, setShowGen] = useState(false);
  const [genForm, setGenForm] = useState({
    liquidacion_id: "",
    banco_id: "",
    formato_id: "",
    cuenta_tesoreria_id: "",
    fecha_pago_programada: "",
    observaciones: "",
  });
  // Cuenta de tesorería elegida en el detalle para confirmar (si no se definió al generar).
  const [confirmCuentaId, setConfirmCuentaId] = useState("");
  const [generando, setGenerando] = useState(false);
  // Mensaje de error de generación, mostrado como banner guía (no toast flotante).
  const [genError, setGenError] = useState(null);

  // Detalle
  const [detalle, setDetalle] = useState(null);

  const totalPages = useMemo(() => Math.max(1, Math.ceil(total / limit)), [total, limit]);

  const cargarCatalogos = async () => {
    try {
      const [bs, fs] = await Promise.all([getBancosRrhh(), getFormatosBancarios()]);
      setBancos(bs || []);
      setFormatos(fs || []);
    } catch {
      toast.error("No se pudieron cargar catálogos");
    }
    // Cuentas de tesorería: best-effort (la empresa puede no tener el módulo).
    try {
      const cuentas = await getTesCuentas({ activo: true });
      const lista = Array.isArray(cuentas) ? cuentas : cuentas?.data || [];
      setTesCuentas(lista.filter((c) => c.activo !== false));
    } catch {
      setTesCuentas([]);
    }
  };

  const cargarLiquidaciones = async () => {
    try {
      const [resp, confirmadas] = await Promise.all([
        getLiquidaciones({ page: 1, limit: 50, estado: "CERRADA" }),
        getAcreditacionesBancarias({ page: 1, limit: 200, estado: "CONFIRMADO" }),
      ]);
      setLiquidacionesCerradas(resp?.data || []);
      setAcreditacionesConfirmadas(confirmadas?.data || []);
    } catch {
      toast.error("No se pudieron cargar las liquidaciones cerradas");
    }
  };

  const load = async () => {
    try {
      setLoading(true);
      const params = { page, limit };
      if (estadoFiltro) params.estado = estadoFiltro;
      if (bancoFiltro) params.banco_id = bancoFiltro;
      const resp = await getAcreditacionesBancarias(params);
      setData(resp?.data || []);
      setTotal(resp?.total || 0);
    } catch {
      toast.error("Error al cargar acreditaciones");
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => { cargarCatalogos(); }, []);
  useEffect(() => { load(); /* eslint-disable-next-line */ }, [page, limit, estadoFiltro, bancoFiltro]);

  const bancoOptions = bancos.map((b) => ({ id: b.id, label: `${b.codigo ? b.codigo + " — " : ""}${b.descripcion}` }));
  const usaTesoreria = tesCuentas.length > 0;
  const tesCuentasPyg = tesCuentas.filter((c) => c.moneda === "PYG");
  const cuentaTesoreriaOptions = tesCuentasPyg.map((c) => ({ id: c.id, label: `${c.nombre} · PYG` }));
  const bancoNombre = (id) => {
    const b = bancos.find((x) => x.id === id);
    return b ? `${b.codigo ? b.codigo + " — " : ""}${b.descripcion}` : "";
  };
  // Cuenta de tesorería del mismo banco que el archivo (para sugerir por defecto).
  const cuentaTesoreriaDelBanco = (bancoId) => tesCuentasPyg.filter((c) => c.banco_id === bancoId);
  // ¿La cuenta elegida es de un banco distinto al del archivo? (aviso no bloqueante)
  const cuentaBancoDistinto = (cuentaId, bancoId) => {
    if (!cuentaId || !bancoId) return false;
    const c = tesCuentasPyg.find((x) => x.id === cuentaId);
    return !!(c && c.banco_id && c.banco_id !== bancoId);
  };
  const formatoOptions = useMemo(() => {
    if (!genForm.banco_id) return [];
    return formatos
      .filter((f) => f.banco_id === genForm.banco_id && f.activo)
      .map((f) => ({ id: f.id, label: `${f.nombre} (${f.tipo_archivo})` }));
  }, [genForm.banco_id, formatos]);
  const liquidacionesDisponibles = useMemo(() => {
    if (!genForm.banco_id) return [];
    const confirmadasDelBanco = new Set(
      acreditacionesConfirmadas
        .filter((a) => a.banco_id === genForm.banco_id)
        .map((a) => a.liquidacion_id),
    );
    return liquidacionesCerradas.filter((l) => !confirmadasDelBanco.has(l.id));
  }, [acreditacionesConfirmadas, genForm.banco_id, liquidacionesCerradas]);
  const liqOptions = liquidacionesDisponibles.map((l) => ({
    id: l.id,
    label: `${fmtPeriodo(l)} · ${l.tipo}${l.sucursal?.descripcion ? " · " + l.sucursal.descripcion : ""} — neto Gs. ${fmtMonto(l.total_neto)}`,
  }));

  const abrirWizard = async () => {
    setGenForm({ liquidacion_id: "", banco_id: "", formato_id: "", cuenta_tesoreria_id: "", fecha_pago_programada: "", observaciones: "" });
    setGenError(null);
    await cargarLiquidaciones();
    setShowGen(true);
  };

  const handleGenerar = async () => {
    if (!genForm.liquidacion_id) return toast.error("Elegí una liquidación");
    if (!genForm.banco_id) return toast.error("Elegí un banco");
    try {
      setGenerando(true);
      setGenError(null);
      const acr = await generarAcreditacionBancaria({
        liquidacion_id: genForm.liquidacion_id,
        banco_id: genForm.banco_id,
        formato_id: genForm.formato_id || undefined,
        cuenta_tesoreria_id: genForm.cuenta_tesoreria_id || undefined,
        fecha_pago_programada: genForm.fecha_pago_programada || undefined,
        observaciones: genForm.observaciones || undefined,
      });
      toast.success(`Archivo generado: ${acr.cantidad_registros} registros · Gs. ${fmtMonto(acr.monto_total)}`);
      setShowGen(false);
      await load();
      handleDescargar(acr);
    } catch (error) {
      // Error mostrado como banner guía dentro del wizard (no toast flotante).
      setGenError(error?.response?.data?.message || "No se pudo generar el archivo de acreditación.");
    } finally {
      setGenerando(false);
    }
  };

  const handleDescargar = async (acr) => {
    try {
      const blob = await descargarAcreditacionBancaria(acr.id);
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = acr.nombre_archivo || "acreditacion.txt";
      document.body.appendChild(a);
      a.click();
      a.remove();
      URL.revokeObjectURL(url);
    } catch {
      toast.error("No se pudo descargar el archivo");
    }
  };

  const handleAbrirDetalle = async (acr) => {
    try {
      const d = await getAcreditacionBancaria(acr.id);
      // Sugerir la cuenta del mismo banco si la acreditación aún no tiene una asignada.
      let cuentaId = d.cuenta_tesoreria?.moneda === "PYG" ? d.cuenta_tesoreria_id || "" : "";
      if (!cuentaId) {
        const match = cuentaTesoreriaDelBanco(d.banco_id);
        if (match.length === 1) cuentaId = match[0].id;
      }
      setConfirmCuentaId(cuentaId);
      setDetalle(d);
    } catch {
      toast.error("No se pudo cargar el detalle");
    }
  };

  const handleEnviar = async (acr) => {
    const ok = await confirm({
      title: "Marcar como enviado",
      message: "Confirmá que el archivo ya fue subido al portal del banco.",
      confirmText: "Marcar enviado",
      confirmColor: "primary",
    });
    if (!ok) return;
    try {
      await enviarAcreditacionBancaria(acr.id);
      toast.success("Marcado como ENVIADO");
      if (detalle?.id === acr.id) setDetalle(await getAcreditacionBancaria(acr.id));
      else load();
    } catch (error) {
      toast.error(error?.response?.data?.message || "No se pudo marcar");
    }
  };

  const handleConfirmar = async (acr, cuentaTesoreriaId) => {
    const cuentaId = cuentaTesoreriaId || acr.cuenta_tesoreria_id || "";
    // Si la empresa usa Tesorería, exigimos la cuenta antes de confirmar (genera el egreso).
    if (usaTesoreria && !cuentaId) {
      return toast.error("Elegí la cuenta de tesorería desde la que se paga para confirmar.");
    }
    const ok = await confirm({
      title: "Confirmar acreditación",
      message: usaTesoreria
        ? "El banco confirmó el pago. Se registrará el egreso en Tesorería desde la cuenta seleccionada."
        : "El banco confirmó que las acreditaciones se procesaron correctamente.",
      confirmText: "Confirmar",
      confirmColor: "success",
    });
    if (!ok) return;
    try {
      await confirmarAcreditacionBancaria(acr.id, cuentaId ? { cuenta_tesoreria_id: cuentaId } : {});
      toast.success("Marcado como CONFIRMADO");
      if (detalle?.id === acr.id) setDetalle(await getAcreditacionBancaria(acr.id));
      else load();
    } catch (error) {
      toast.error(error?.response?.data?.message || "No se pudo confirmar");
    }
  };

  const handleAnular = async (acr) => {
    const comentario = await prompt({
      title: "Anular acreditación",
      label: "Motivo",
      placeholder: "Opcional",
      confirmText: "Anular",
      confirmColor: "warning",
    });
    if (comentario === null) return;
    try {
      await anularAcreditacionBancaria(acr.id, comentario ? { comentario } : {});
      toast.success("Anulada");
      if (detalle?.id === acr.id) setDetalle(null);
      load();
    } catch (error) {
      toast.error(error?.response?.data?.message || "No se pudo anular");
    }
  };

  const updateGen = (k, v) => setGenForm((p) => ({ ...p, [k]: v }));

  // ════════════════════════════════════════════════════════
  // Wizard
  // ════════════════════════════════════════════════════════
  if (showGen) {
    return (
      <Container>
        <FormPanel>
          <FormHead>
            <SectionTitle><Icon icon="lucide:file-plus-2" /> Generar archivo de acreditación</SectionTitle>
            <GhostButton onClick={() => setShowGen(false)}><Icon icon="lucide:x" /> Cerrar</GhostButton>
          </FormHead>
          <Alert severity="info" sx={{ mb: 2 }}>
            Se incluyen empleados con <strong>cuenta del banco seleccionado</strong> y <strong>neto a pagar &gt; 0</strong> en la liquidación.
            Si no especificás formato, se usa el activo más reciente del banco.
          </Alert>

          {genError && (
            <Alert severity="warning" sx={{ mb: 2 }} onClose={() => setGenError(null)}>
              <AlertTitle>{genError}</AlertTitle>
              <Typography variant="body2" sx={{ mb: 1 }}>
                Para que un empleado entre en el archivo del banco elegido, su ficha debe cumplir:
              </Typography>
              <Box component="ul" sx={{ pl: 2.5, m: 0, mb: 1.5 }}>
                <li><Typography variant="body2">El <strong>banco</strong> del empleado debe ser el mismo que elegiste arriba.</Typography></li>
                <li><Typography variant="body2">Debe tener cargado el <strong>número de cuenta bancaria</strong>.</Typography></li>
                <li><Typography variant="body2">Su <strong>neto a pagar</strong> en esta liquidación debe ser mayor a 0.</Typography></li>
              </Box>
              <Stack direction="row" spacing={1} flexWrap="wrap">
                <Button
                  size="small"
                  variant="outlined"
                  color="warning"
                  startIcon={<Icon icon="lucide:users" width={14} />}
                  onClick={() => setActiveTab && setActiveTab("empleados")}
                >
                  Ir a Empleados (banco y cuenta)
                </Button>
                <Button
                  size="small"
                  variant="text"
                  color="inherit"
                  startIcon={<Icon icon="lucide:refresh-cw" width={14} />}
                  onClick={() => { updateGen("banco_id", ""); updateGen("formato_id", ""); setGenError(null); }}
                >
                  Elegir otro banco
                </Button>
              </Stack>
            </Alert>
          )}
          <FieldsGrid $cols={4}>
            <Field $span={2}>
              <label>Banco *</label>
              <SearchableSelect options={bancoOptions} value={genForm.banco_id}
                onChange={(id) => {
                  const match = cuentaTesoreriaDelBanco(id);
                  setGenForm((p) => ({
                    ...p,
                    banco_id: id || "",
                    formato_id: "",
                    liquidacion_id: "",
                    cuenta_tesoreria_id: match.length === 1 ? match[0].id : "",
                    fecha_pago_programada: "",
                  }));
                  setGenError(null);
                }}
                placeholder="Elegí un banco…" />
            </Field>
            <Field $span={2}>
              <label>Liquidación cerrada *</label>
              <SearchableSelect options={liqOptions} value={genForm.liquidacion_id}
                onChange={(id) => {
                  updateGen("liquidacion_id", id || "");
                  setGenError(null);
                  // Pre-cargar la fecha de pago desde la liquidación elegida (editable).
                  const liq = liquidacionesDisponibles.find((l) => l.id === id);
                  updateGen("fecha_pago_programada", (liq?.fecha_pago_programada || "").slice(0, 10));
                }}
                placeholder={genForm.banco_id ? "Elegí el período…" : "Elegí un banco primero"}
                disabled={!genForm.banco_id}
                noOptionsText="No hay liquidaciones pendientes para este banco" />
              <Typography variant="caption" color="text.disabled">
                No se muestran liquidaciones que ya tienen acreditación CONFIRMADA para el banco seleccionado.
              </Typography>
            </Field>
            <Field $span={2}>
              <label>Formato (opcional)</label>
              <SearchableSelect options={formatoOptions} value={genForm.formato_id}
                onChange={(id) => updateGen("formato_id", id || "")}
                placeholder={genForm.banco_id ? "Usar formato activo por defecto" : "Elegí un banco primero"}
                disabled={!genForm.banco_id} />
            </Field>
            {usaTesoreria && (
              <Field $span={2}>
                <label>Cuenta de tesorería (pago)</label>
                <SearchableSelect options={cuentaTesoreriaOptions} value={genForm.cuenta_tesoreria_id}
                  onChange={(id) => updateGen("cuenta_tesoreria_id", id || "")}
                  placeholder="Desde qué cuenta PYG se paga…"
                  noOptionsText="No hay cuentas de tesorería en PYG" />
                {cuentaBancoDistinto(genForm.cuenta_tesoreria_id, genForm.banco_id) ? (
                  <Typography variant="caption" sx={{ color: "warning.main" }}>
                    ⚠ La cuenta elegida es de otro banco distinto al del archivo ({bancoNombre(genForm.banco_id)}). Suele pagarse desde una cuenta del mismo banco; verificá que sea intencional.
                  </Typography>
                ) : (
                  <Typography variant="caption" color="text.disabled">
                    La nómina se paga en PYG. No se listan cuentas USD para evitar diferencias de moneda en Tesorería y Contabilidad.
                  </Typography>
                )}
              </Field>
            )}
            <Field>
              <label>Fecha de pago programada</label>
              <input type="date" value={genForm.fecha_pago_programada}
                onChange={(e) => updateGen("fecha_pago_programada", e.target.value)} />
              <Typography variant="caption" color="text.disabled">
                Se toma de la liquidación; podés ajustarla.
              </Typography>
            </Field>
            <Field $span={3}>
              <label>Observaciones</label>
              <input value={genForm.observaciones}
                onChange={(e) => updateGen("observaciones", e.target.value)} />
            </Field>
          </FieldsGrid>
          <Footer>
            <FooterActionButton type="button" $variant="danger" disabled={generando} onClick={() => setShowGen(false)}>
              <Icon icon="lucide:x-circle" /> Cancelar
            </FooterActionButton>
            <FooterActionButton type="button" $variant="primary" disabled={generando} onClick={handleGenerar}>
              <Icon icon="lucide:download" /> {generando ? "Generando…" : "Generar y descargar"}
            </FooterActionButton>
          </Footer>
        </FormPanel>
        {dialogs}
      </Container>
    );
  }

  // ════════════════════════════════════════════════════════
  // Detalle (vista in-place)
  // ════════════════════════════════════════════════════════
  if (detalle) {
    const acr = detalle;
    const esGen = acr.estado === "GENERADO";
    const esEnv = acr.estado === "ENVIADO";
    const puedeEnviar = esGen;
    const puedeConfirmar = esGen || esEnv;
    const puedeAnular = acr.estado !== "CONFIRMADO" && acr.estado !== "ANULADO";

    return (
      <Container>
        <FormPanel>
          <FormHead>
            <SectionTitle>
              <Icon icon="lucide:building" /> Acreditación · {acr.banco?.descripcion} · {fmtPeriodo(acr.liquidacion)}
              {" "}<Badge $state={acr.estado}>{acr.estado}</Badge>
            </SectionTitle>
            <Box sx={{ display: "flex", gap: 0.5 }}>
              <GhostButton onClick={() => handleDescargar(acr)}>
                <Icon icon="lucide:download" /> Descargar archivo
              </GhostButton>
              {puedeEnviar && (
                <GhostButton onClick={() => handleEnviar(acr)}>
                  <Icon icon="lucide:send" /> Marcar enviado
                </GhostButton>
              )}
              {puedeConfirmar && (
                <FooterActionButton type="button" $variant="primary" onClick={() => handleConfirmar(acr, confirmCuentaId)}>
                  <Icon icon="lucide:check-circle" /> Confirmar
                </FooterActionButton>
              )}
              {puedeAnular && (
                <GhostButton onClick={() => handleAnular(acr)}>
                  <Icon icon="lucide:ban" /> Anular
                </GhostButton>
              )}
              <GhostButton onClick={() => { setDetalle(null); load(); }}>
                <Icon icon="lucide:arrow-left" /> Volver
              </GhostButton>
            </Box>
          </FormHead>

          <FieldsGrid $cols={4}>
            <Field><label>Banco</label><input readOnly value={acr.banco?.descripcion || "—"} /></Field>
            <Field><label>Formato</label><input readOnly value={acr.formato?.nombre || "—"} /></Field>
            {usaTesoreria && puedeConfirmar ? (
              <Field $span={2}>
                <label>Cuenta de tesorería (pago) *</label>
                <SearchableSelect options={cuentaTesoreriaOptions} value={confirmCuentaId}
                  onChange={(id) => setConfirmCuentaId(id || "")}
                  placeholder="Desde qué cuenta PYG se paga…"
                  noOptionsText="No hay cuentas de tesorería en PYG" />
                {cuentaBancoDistinto(confirmCuentaId, acr.banco_id) && (
                  <Typography variant="caption" sx={{ color: "warning.main" }}>
                    ⚠ La cuenta es de otro banco distinto al del archivo ({acr.banco?.descripcion}). Verificá que sea intencional.
                  </Typography>
                )}
              </Field>
            ) : (
              <Field><label>Cuenta de tesorería</label><input readOnly value={acr.cuenta_tesoreria ? `${acr.cuenta_tesoreria.nombre} · ${acr.cuenta_tesoreria.moneda || "PYG"}` : "—"} /></Field>
            )}
            <Field><label>Período</label><input readOnly value={fmtPeriodo(acr.liquidacion)} /></Field>
            <Field><label>Pago programado</label><input readOnly value={fmtFecha(acr.fecha_pago_programada)} /></Field>
            <Field><label>Registros</label><input readOnly value={acr.cantidad_registros} /></Field>
            <Field><label>Monto total</label><input readOnly value={`Gs. ${fmtMonto(acr.monto_total)}`} /></Field>
            <Field><label>Archivo</label><input readOnly value={acr.nombre_archivo} /></Field>
            <Field><label>Encoding</label><input readOnly value={acr.encoding} /></Field>
            <Field><label>Generado</label><input readOnly value={fmtFechaHora(acr.fecha_generacion)} /></Field>
            <Field><label>Enviado</label><input readOnly value={fmtFechaHora(acr.fecha_envio)} /></Field>
            <Field><label>Confirmado</label><input readOnly value={fmtFechaHora(acr.fecha_confirmacion)} /></Field>
            <Field><label>Anulado</label><input readOnly value={fmtFechaHora(acr.fecha_anulacion)} /></Field>
          </FieldsGrid>

          <Divider />
          <SectionTitle><Icon icon="lucide:file-text" /> Contenido del archivo</SectionTitle>
          <Box
            component="pre"
            sx={{
              maxHeight: 320,
              overflow: "auto",
              p: 2,
              fontFamily: "monospace",
              fontSize: "0.8rem",
              border: "1px solid",
              borderColor: "divider",
              borderRadius: 1,
              background: "rgba(0,0,0,0.04)",
              whiteSpace: "pre",
            }}
          >
            {acr.contenido_archivo}
          </Box>
        </FormPanel>
        {dialogs}
      </Container>
    );
  }

  // ════════════════════════════════════════════════════════
  // Listado
  // ════════════════════════════════════════════════════════
  return (
    <Container id="rrhh-acr-list-view">
      <RRHHGuia seccion="acreditaciones" />
      <RRHHPrereqChecklist tabKey="acreditaciones" />
      <ListPanel>
        <ListBody>
          <ToolBar id="rrhh-acr-toolbar">
            <Box sx={{ minWidth: 180 }}>
              <SearchableSelect label="Estado" options={ESTADO_OPTIONS} value={estadoFiltro}
                onChange={(id) => { setEstadoFiltro(id || ""); setPage(1); }}
                placeholder="Todos los estados" />
            </Box>
            <Box sx={{ minWidth: 240 }}>
              <SearchableSelect label="Banco" options={bancoOptions} value={bancoFiltro}
                onChange={(id) => { setBancoFiltro(id || ""); setPage(1); }}
                placeholder="Todos los bancos" />
            </Box>
            <Tooltip title="Refrescar">
              <GhostButton onClick={load} disabled={loading}><Icon icon="lucide:refresh-cw" /></GhostButton>
            </Tooltip>
            <Box sx={{ flex: 1 }} />
            <FooterActionButton id="rrhh-acr-generar-btn" type="button" $variant="primary" onClick={abrirWizard}>
              <Icon icon="lucide:plus" /> Generar acreditación
            </FooterActionButton>
          </ToolBar>

          <div id="rrhh-acr-list-content">
            {loading ? (
              <EmptyState>Cargando…</EmptyState>
            ) : data.length === 0 ? (
              <RRHHEmptyState
                icon="lucide:building"
                titulo="Sin acreditaciones generadas"
                descripcion="Las acreditaciones bancarias transfieren el sueldo neto a la cuenta de cada empleado. Requieren una liquidación cerrada y un formato bancario configurado."
                ctaLabel="Generar acreditación"
                onCta={abrirWizard}
                guiaSeccion="acreditaciones"
              />
            ) : (
              <TableWrap id="rrhh-acr-table">
                <table>
                  <thead>
                    <tr>
                      <th>Banco</th>
                      <th>Período</th>
                      <th>Formato</th>
                      <th style={{ textAlign: "right" }}>Registros</th>
                      <th style={{ textAlign: "right" }}>Monto total</th>
                      <th>Archivo</th>
                      <th>Estado</th>
                      <th>Generado</th>
                      <th style={{ textAlign: "center" }}>Acciones</th>
                    </tr>
                  </thead>
                  <tbody>
                    {data.map((acr) => {
                      const esGen = acr.estado === "GENERADO";
                      const esEnv = acr.estado === "ENVIADO";
                      return (
                        <tr key={acr.id}>
                          <td>{acr.banco?.descripcion || "—"}</td>
                          <td>{fmtPeriodo(acr.liquidacion)}</td>
                          <td>{acr.formato?.nombre || "—"}</td>
                          <td style={{ textAlign: "right" }}>{acr.cantidad_registros}</td>
                          <td style={{ textAlign: "right", fontFamily: "monospace", fontWeight: 600 }}>{fmtMonto(acr.monto_total)}</td>
                          <td style={{ fontSize: "0.8rem" }}>{acr.nombre_archivo}</td>
                          <td><Badge $state={acr.estado}>{acr.estado}</Badge></td>
                          <td>{fmtFecha(acr.fecha_generacion)}</td>
                          <td style={{ textAlign: "center" }}>
                            <RowActions>
                              <Tooltip title="Ver detalle">
                                <IconButton size="small" onClick={() => handleAbrirDetalle(acr)}>
                                  <Icon icon="lucide:eye" width={16} />
                                </IconButton>
                              </Tooltip>
                              <Tooltip title="Descargar">
                                <IconButton size="small" color="primary" onClick={() => handleDescargar(acr)}>
                                  <Icon icon="lucide:download" width={16} />
                                </IconButton>
                              </Tooltip>
                              {esGen && (
                                <Tooltip title="Marcar enviado">
                                  <IconButton size="small" color="info" onClick={() => handleEnviar(acr)}>
                                    <Icon icon="lucide:send" width={16} />
                                  </IconButton>
                                </Tooltip>
                              )}
                              {(esGen || esEnv) && (
                                <Tooltip title="Confirmar">
                                  <IconButton size="small" color="success" onClick={() => handleConfirmar(acr)}>
                                    <Icon icon="lucide:check-circle" width={16} />
                                  </IconButton>
                                </Tooltip>
                              )}
                              {acr.estado !== "CONFIRMADO" && acr.estado !== "ANULADO" && (
                                <Tooltip title="Anular">
                                  <IconButton size="small" color="error" onClick={() => handleAnular(acr)}>
                                    <Icon icon="lucide:ban" width={16} />
                                  </IconButton>
                                </Tooltip>
                              )}
                            </RowActions>
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </TableWrap>
            )}
          </div>

          <TablePaginationBar
            page={page}
            totalPages={totalPages}
            onPageChange={setPage}
            total={total}
            shown={data.length}
            noun="acreditaciones"
            rowsPerPage={limit}
            onRowsPerPageChange={(n) => {
              setLimit(n);
              setPage(1);
            }}
          />
        </ListBody>
      </ListPanel>
      {dialogs}
    </Container>
  );
}
