import { Icon } from "@iconify/react";
import { Download, Search, SwapHoriz } from "@mui/icons-material";
import * as XLSX from "xlsx";
import {
  Button,
  Chip,
  CircularProgress,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  FormControl,
  InputAdornment,
  InputLabel,
  MenuItem,
  Select,
  TextField,
  Tooltip,
  Typography,
} from "@mui/material";
import { useEffect, useMemo, useState } from "react";
import { getTipoCambioVigente } from "../../api/contabilidad.service";
import styled from "styled-components";
import { MonedaInput } from "../common/MonedaInput";
import { usePermission } from "../../hooks/usePermission";
import {
  useAnularTesTransferenciaMutation,
  useContabilizarTesTransferenciaMutation,
  useCreateTesTransferenciaMutation,
  useTesCuentasQuery,
  useTesTransferenciasQuery,
} from "../../tanstack/TesoreriaStack";
import { sanitizeRecords } from "../_standards";
import { hoyISO } from "../../utils/fecha";

// ─── helpers ────────────────────────────────────────────────────────────────

const todayStr = () => hoyISO();
const hace30 = () => {
  const d = new Date();
  d.setDate(d.getDate() - 30);
  return d.toISOString().split("T")[0];
};

const fmtFecha = (val) => {
  if (!val) return "—";
  const m = String(val).match(/^(\d{4})-(\d{2})-(\d{2})/);
  return m ? `${m[3]}/${m[2]}/${m[1]}` : val;
};

const fmtMonto = (n, moneda = "PYG") => {
  const val = Number(n || 0);
  if (moneda === "PYG") return `Gs. ${val.toLocaleString("es-PY", { maximumFractionDigits: 0 })}`;
  return `${moneda} ${val.toLocaleString("es-PY", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
};

const ESTADO_COLORS = { CONFIRMADO: "success", ANULADO: "error" };

const exportarExcelTransferencias = (datos) => {
  const rows = datos.map(t => ({
    "Fecha": fmtFecha(t.fecha),
    "Cuenta Origen": t.cuenta_origen?.nombre || "",
    "Moneda Origen": t.cuenta_origen?.moneda || "",
    "Monto Origen": Number(t.monto_origen || t.monto || 0),
    "Cuenta Destino": t.cuenta_destino?.nombre || "",
    "Moneda Destino": t.cuenta_destino?.moneda || "",
    "Monto Destino": Number(t.monto_destino || t.monto || 0),
    "Tipo de Cambio": t.tipo_cambio || "",
    "Estado": t.estado || "",
    "Descripción": t.descripcion || "",
    "Motivo Anulación": t.motivo_anulacion || "",
  }));
  const ws = XLSX.utils.json_to_sheet(sanitizeRecords(rows));
  const wb = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(wb, ws, "Transferencias");
  XLSX.writeFile(wb, `transferencias_${hoyISO()}.xlsx`);
};
const PAGE_SIZE = 20;

// ─── component ──────────────────────────────────────────────────────────────

export function TesTranferenciasTab() {
  const [filters, setFilters] = useState({
    fecha_desde: hace30(),
    fecha_hasta: todayStr(),
    cuenta_id: "",
    estado: "",
  });
  const [busqueda, setBusqueda] = useState("");
  const [page, setPage] = useState(1);

  const [openNew, setOpenNew] = useState(false);
  const [anularTarget, setAnularTarget] = useState(null);
  const [motivoAnulacion, setMotivoAnulacion] = useState("");
  const [form, setForm] = useState({
    cuenta_origen_id: "",
    cuenta_destino_id: "",
    monto: 0,
    fecha: todayStr(),
    descripcion: "",
    tipo_cambio: "",
  });

  const { data: transferenciasRaw = [], isLoading } = useTesTransferenciasQuery({
    desde: filters.fecha_desde || undefined,
    hasta: filters.fecha_hasta || undefined,
    cuenta_id: filters.cuenta_id || undefined,
    estado: filters.estado || undefined,
  });

  const { data: cuentasData } = useTesCuentasQuery({ soloActivas: true });
  const cuentas = useMemo(() => {
    const arr = Array.isArray(cuentasData) ? cuentasData : (cuentasData?.data || []);
    return arr.filter((c) => c.activo !== false);
  }, [cuentasData]);

  // Búsqueda local
  const filtered = useMemo(() => {
    const q = busqueda.trim().toLowerCase();
    if (!q) return transferenciasRaw;
    return transferenciasRaw.filter(
      (t) =>
        (t.cuenta_origen?.nombre || "").toLowerCase().includes(q) ||
        (t.cuenta_destino?.nombre || "").toLowerCase().includes(q) ||
        (t.descripcion || "").toLowerCase().includes(q),
    );
  }, [transferenciasRaw, busqueda]);

  const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
  const safePage = Math.min(page, totalPages);
  const paginated = filtered.slice((safePage - 1) * PAGE_SIZE, safePage * PAGE_SIZE);

  const [tcSistema, setTcSistema] = useState(null); // TC de referencia de Contabilidad

  const crearMutation = useCreateTesTransferenciaMutation();
  const anularMutation = useAnularTesTransferenciaMutation();
  const contabilizarMutation = useContabilizarTesTransferenciaMutation();
  // Mismo permiso que "Regenerar" de Conciliación, y solo con el módulo Contabilidad.
  const permisoContabilidad = usePermission("CONTABILIDAD");
  const puedeContabilizar = permisoContabilidad.hasAccess && permisoContabilidad.can("CONT_CONC_REGENERAR");

  const setFilter = (key, val) => { setFilters((f) => ({ ...f, [key]: val })); setPage(1); };

  const cuentaOrigen = cuentas.find((c) => c.id === form.cuenta_origen_id);
  const cuentaDestino = cuentas.find((c) => c.id === form.cuenta_destino_id);
  const monedaDistinta = cuentaOrigen && cuentaDestino && cuentaOrigen.moneda !== cuentaDestino.moneda;
  // TC siempre expresado como "1 moneda_extranjera = X PYG" (convención estándar Paraguay)
  // PYG → extranjera: dividir.  extranjera → PYG: multiplicar.
  const origenEsPYG = cuentaOrigen?.moneda === "PYG";
  const monedaExtranjera = origenEsPYG ? cuentaDestino?.moneda : cuentaOrigen?.moneda;

  // Consultar TC sistema cuando cambia la moneda extranjera o la fecha
  useEffect(() => {
    if (!monedaDistinta || !monedaExtranjera || !form.fecha) { setTcSistema(null); return; }
    getTipoCambioVigente(monedaExtranjera, form.fecha)
      .then(data => setTcSistema(data ? Number(data.tasa) : null))
      .catch(() => setTcSistema(null));
  }, [monedaDistinta, monedaExtranjera, form.fecha]);

  const tc = Number(form.tipo_cambio) || 0;
  // Mismo margen que el servidor (tipo-cambio-transferencia.ts): más de 20 % de la
  // cotización del día es casi seguro un cero de más o de menos.
  const tcLejos = Boolean(monedaDistinta && tcSistema && tc > 0 && Math.abs(tc - tcSistema) / tcSistema > 0.2);
  const montoDestino = monedaDistinta && tc > 0
    ? (origenEsPYG ? form.monto / tc : form.monto * tc)
    : form.monto;

  const formValid =
    form.cuenta_origen_id &&
    form.cuenta_destino_id &&
    form.cuenta_origen_id !== form.cuenta_destino_id &&
    form.monto > 0 &&
    form.fecha &&
    (!monedaDistinta || (tc > 0 && !tcLejos));

  const resetForm = () =>
    setForm({ cuenta_origen_id: "", cuenta_destino_id: "", monto: 0, fecha: todayStr(), descripcion: "", tipo_cambio: "" });

  const handleCrear = () => {
    crearMutation.mutate(
      {
        cuenta_origen_id: form.cuenta_origen_id,
        cuenta_destino_id: form.cuenta_destino_id,
        monto: form.monto,
        fecha: form.fecha,
        descripcion: form.descripcion || undefined,
        tipo_cambio: monedaDistinta && form.tipo_cambio ? Number(form.tipo_cambio) : undefined,
      },
      { onSuccess: () => { setOpenNew(false); resetForm(); } },
    );
  };

  const handleAnular = () => {
    if (!motivoAnulacion.trim()) return;
    anularMutation.mutate(
      { id: anularTarget.id, data: { motivo: motivoAnulacion } },
      { onSuccess: () => { setAnularTarget(null); setMotivoAnulacion(""); } },
    );
  };

  return (
    <Container>
      {/* ── Barra filtros + botón ── */}
      <FiltersBar>
        <TextField
          label="Buscar"
          size="small"
          placeholder="Origen, destino, descripción..."
          value={busqueda}
          onChange={(e) => { setBusqueda(e.target.value); setPage(1); }}
          InputProps={{ startAdornment: <InputAdornment position="start"><Search fontSize="small" /></InputAdornment> }}
          sx={{ flex: "1 1 180px", minWidth: 160 }}
        />
        <TextField
          label="Desde"
          type="date"
          size="small"
          value={filters.fecha_desde}
          onChange={(e) => setFilter("fecha_desde", e.target.value)}
          InputLabelProps={{ shrink: true }}
          sx={{ width: 145 }}
        />
        <TextField
          label="Hasta"
          type="date"
          size="small"
          value={filters.fecha_hasta}
          onChange={(e) => setFilter("fecha_hasta", e.target.value)}
          InputLabelProps={{ shrink: true }}
          sx={{ width: 145 }}
        />
        <FormControl size="small" sx={{ flex: "1 1 160px", minWidth: 150 }}>
          <InputLabel>Cuenta</InputLabel>
          <Select value={filters.cuenta_id} label="Cuenta" onChange={(e) => setFilter("cuenta_id", e.target.value)}>
            <MenuItem value="">Todas</MenuItem>
            {cuentas.map((c) => <MenuItem key={c.id} value={c.id}>{c.nombre}</MenuItem>)}
          </Select>
        </FormControl>
        <FormControl size="small" sx={{ minWidth: 120 }}>
          <InputLabel>Estado</InputLabel>
          <Select value={filters.estado} label="Estado" onChange={(e) => setFilter("estado", e.target.value)}>
            <MenuItem value="">Todos</MenuItem>
            <MenuItem value="CONFIRMADO">Confirmado</MenuItem>
            <MenuItem value="ANULADO">Anulado</MenuItem>
          </Select>
        </FormControl>
        <Tooltip title="Exportar a Excel">
          <Button
            size="small"
            variant="outlined"
            startIcon={<Download />}
            onClick={() => exportarExcelTransferencias(filtered)}
            disabled={filtered.length === 0}
          >
            Excel
          </Button>
        </Tooltip>
        <Button
          variant="contained"
          startIcon={<SwapHoriz />}
          onClick={() => setOpenNew(true)}
          sx={{ background: "#0ea5e9", "&:hover": { background: "#0284c7" }, whiteSpace: "nowrap", ml: "auto" }}
        >
          Nueva Transferencia
        </Button>
      </FiltersBar>

      {/* ── Tabla desktop ── */}
      <TableWrap className="desktop-table">
        <table style={{ width: "100%", borderCollapse: "collapse", minWidth: 720 }}>
          <thead>
            <tr>
              <Th>Fecha</Th>
              <Th>Origen</Th>
              <Th style={{ textAlign: "center", width: 30 }}></Th>
              <Th>Destino</Th>
              <Th style={{ textAlign: "right" }}>Monto origen</Th>
              <Th style={{ textAlign: "right" }}>Monto destino</Th>
              <Th>Descripción</Th>
              <Th>Estado</Th>
              <Th>Acciones</Th>
            </tr>
          </thead>
          <tbody>
            {isLoading ? (
              <tr><Td colSpan={9} style={{ textAlign: "center", padding: 32 }}><CircularProgress size={24} /></Td></tr>
            ) : paginated.length === 0 ? (
              <tr>
                <Td colSpan={9} style={{ textAlign: "center", padding: 40, opacity: 0.5 }}>
                  {busqueda ? "Sin resultados para la búsqueda" : "No hay transferencias en el período seleccionado"}
                </Td>
              </tr>
            ) : paginated.map((t) => (
              <Tr key={t.id}>
                <Td style={{ whiteSpace: "nowrap" }}>{fmtFecha(t.fecha)}</Td>
                <Td>
                  <CuentaCell>
                    <span>{t.cuenta_origen?.nombre || "—"}</span>
                    <MonedaBadge>{t.cuenta_origen?.moneda || ""}</MonedaBadge>
                  </CuentaCell>
                </Td>
                <Td style={{ textAlign: "center", color: "#94a3b8", padding: "10px 4px" }}>
                  <Icon icon="lucide:arrow-right" style={{ fontSize: 14 }} />
                </Td>
                <Td>
                  <CuentaCell>
                    <span>{t.cuenta_destino?.nombre || "—"}</span>
                    <MonedaBadge>{t.cuenta_destino?.moneda || ""}</MonedaBadge>
                  </CuentaCell>
                </Td>
                <Td style={{ textAlign: "right", whiteSpace: "nowrap" }}>
                  <MontoEgreso>{fmtMonto(t.monto_origen, t.cuenta_origen?.moneda)}</MontoEgreso>
                </Td>
                <Td style={{ textAlign: "right", whiteSpace: "nowrap" }}>
                  <MontoIngreso>{fmtMonto(t.monto_destino, t.cuenta_destino?.moneda)}</MontoIngreso>
                </Td>
                <Td style={{ maxWidth: 220, wordBreak: "break-word", fontSize: 12, opacity: 0.75 }}>
                  {t.descripcion || "—"}
                </Td>
                <Td>
                  <Chip label={t.estado} color={ESTADO_COLORS[t.estado] || "default"} size="small" />
                </Td>
                <Td>
                  <AccionesFila>
                  {t.estado === "CONFIRMADO" && (
                    <Tooltip title="Anular esta transferencia y revertir saldos">
                      <Button
                        size="small"
                        variant="outlined"
                        color="error"
                        onClick={() => { setAnularTarget(t); setMotivoAnulacion(""); }}
                      >
                        Anular
                      </Button>
                    </Tooltip>
                  )}
                  {t.estado === "CONFIRMADO" && puedeContabilizar && (
                    <Tooltip title="Volver a generar el asiento si quedó sin contabilizar (por ejemplo, por falta de mapeo). Si ya tiene asiento, no lo duplica.">
                      <span>
                        <Button
                          size="small"
                          variant="outlined"
                          startIcon={<Icon icon="lucide:refresh-cw" />}
                          sx={{ whiteSpace: "nowrap" }}
                          disabled={contabilizarMutation.isPending}
                          onClick={() => contabilizarMutation.mutate(t.id)}
                        >
                          Reintentar contabilización
                        </Button>
                      </span>
                    </Tooltip>
                  )}
                  {t.estado === "ANULADO" && t.motivo_anulacion && (
                    <Tooltip title={`Motivo: ${t.motivo_anulacion}`}>
                      <span style={{ fontSize: 11, opacity: 0.6, cursor: "help" }}>ver motivo</span>
                    </Tooltip>
                  )}
                  </AccionesFila>
                </Td>
              </Tr>
            ))}
          </tbody>
        </table>

        <Pagination>
          <Typography variant="caption" sx={{ opacity: 0.6 }}>
            {filtered.length === 0 ? "Sin resultados" : `Página ${safePage} de ${totalPages} (${filtered.length} registros)`}
          </Typography>
          <Button size="small" disabled={safePage <= 1} onClick={() => setPage((p) => p - 1)}>Anterior</Button>
          <Button size="small" disabled={safePage >= totalPages} onClick={() => setPage((p) => p + 1)}>Siguiente</Button>
        </Pagination>
      </TableWrap>

      {/* ── Cards mobile ── */}
      <CardList className="mobile-cards">
        {isLoading ? (
          <div style={{ textAlign: "center", padding: 32 }}><CircularProgress size={24} /></div>
        ) : paginated.length === 0 ? (
          <EmptyMsg>{busqueda ? "Sin resultados para la búsqueda" : "No hay transferencias en el período seleccionado"}</EmptyMsg>
        ) : paginated.map((t) => (
          <MobCard key={t.id}>
            <MobCardTop>
              <Chip label={t.estado} color={ESTADO_COLORS[t.estado] || "default"} size="small" />
              <MobFecha>{fmtFecha(t.fecha)}</MobFecha>
            </MobCardTop>
            <MobFlow>
              <MobCuenta>
                <MobCuentaLabel>ORIGEN</MobCuentaLabel>
                <MobCuentaNombre>{t.cuenta_origen?.nombre || "—"}</MobCuentaNombre>
                <MontoEgreso style={{ fontSize: 13 }}>{fmtMonto(t.monto_origen, t.cuenta_origen?.moneda)}</MontoEgreso>
              </MobCuenta>
              <MobArrow><Icon icon="lucide:arrow-right" /></MobArrow>
              <MobCuenta>
                <MobCuentaLabel>DESTINO</MobCuentaLabel>
                <MobCuentaNombre>{t.cuenta_destino?.nombre || "—"}</MobCuentaNombre>
                <MontoIngreso style={{ fontSize: 13 }}>{fmtMonto(t.monto_destino, t.cuenta_destino?.moneda)}</MontoIngreso>
              </MobCuenta>
            </MobFlow>
            {t.descripcion && <MobDesc>{t.descripcion}</MobDesc>}
            {t.estado === "CONFIRMADO" && (
              <div style={{ marginTop: 6 }}>
                <Button size="small" variant="outlined" color="error"
                  onClick={() => { setAnularTarget(t); setMotivoAnulacion(""); }}>
                  Anular
                </Button>
                {puedeContabilizar && (
                  <Button size="small" variant="outlined" sx={{ ml: 1 }}
                    disabled={contabilizarMutation.isPending}
                    onClick={() => contabilizarMutation.mutate(t.id)}>
                    Reintentar contabilización
                  </Button>
                )}
              </div>
            )}
            {t.estado === "ANULADO" && t.motivo_anulacion && (
              <MobDesc style={{ color: "#ef4444", fontStyle: "normal" }}>Motivo: {t.motivo_anulacion}</MobDesc>
            )}
          </MobCard>
        ))}
        <Pagination style={{ borderTop: "none", justifyContent: "center" }}>
          <Typography variant="caption" sx={{ opacity: 0.6 }}>
            {filtered.length === 0 ? "Sin resultados" : `Pág. ${safePage}/${totalPages} (${filtered.length})`}
          </Typography>
          <Button size="small" disabled={safePage <= 1} onClick={() => setPage((p) => p - 1)}>Ant</Button>
          <Button size="small" disabled={safePage >= totalPages} onClick={() => setPage((p) => p + 1)}>Sig</Button>
        </Pagination>
      </CardList>

      {/* ── Modal nueva transferencia ── */}
      <Dialog open={openNew} onClose={() => { setOpenNew(false); resetForm(); }} maxWidth="sm" fullWidth>
        <DialogTitle sx={{ fontWeight: 700, display: "flex", alignItems: "center", gap: 1 }}>
          <SwapHoriz /> Nueva Transferencia entre cuentas
        </DialogTitle>
        <DialogContent sx={{ pt: "16px !important", display: "flex", flexDirection: "column", gap: 2 }}>
          <FormControl size="small" fullWidth>
            <InputLabel id="transf-origen-label">Cuenta de origen *</InputLabel>
            <Select
              labelId="transf-origen-label"
              label="Cuenta de origen *"
              value={form.cuenta_origen_id}
              onChange={(e) => setForm((f) => ({ ...f, cuenta_origen_id: e.target.value }))}
            >
              <MenuItem value="" disabled><em>Seleccioná la cuenta que envía</em></MenuItem>
              {cuentas.map((c) => (
                <MenuItem key={c.id} value={c.id} disabled={c.id === form.cuenta_destino_id}>
                  <span style={{ fontWeight: 600 }}>{c.nombre}</span>
                  <span style={{ marginLeft: 8, opacity: 0.6, fontSize: 12 }}>{c.moneda} · saldo: {fmtMonto(c.saldo_actual, c.moneda)}</span>
                </MenuItem>
              ))}
            </Select>
          </FormControl>

          <FormControl size="small" fullWidth>
            <InputLabel id="transf-destino-label">Cuenta de destino *</InputLabel>
            <Select
              labelId="transf-destino-label"
              label="Cuenta de destino *"
              value={form.cuenta_destino_id}
              onChange={(e) => setForm((f) => ({ ...f, cuenta_destino_id: e.target.value }))}
            >
              <MenuItem value="" disabled><em>Seleccioná la cuenta que recibe</em></MenuItem>
              {cuentas.map((c) => (
                <MenuItem key={c.id} value={c.id} disabled={c.id === form.cuenta_origen_id}>
                  <span style={{ fontWeight: 600 }}>{c.nombre}</span>
                  <span style={{ marginLeft: 8, opacity: 0.6, fontSize: 12 }}>{c.moneda} · saldo: {fmtMonto(c.saldo_actual, c.moneda)}</span>
                </MenuItem>
              ))}
            </Select>
          </FormControl>

          <div style={{ display: "flex", gap: 10 }}>
            <MonedaInput
              label={`Monto a transferir *${cuentaOrigen ? ` (${cuentaOrigen.moneda})` : ""}`}
              value={form.monto}
              onChange={(v) => setForm((f) => ({ ...f, monto: v }))}
              moneda={cuentaOrigen?.moneda || "PYG"}
              sx={{ flex: 1 }}
            />
            <TextField
              size="small"
              type="date"
              label="Fecha *"
              value={form.fecha}
              onChange={(e) => setForm((f) => ({ ...f, fecha: e.target.value }))}
              InputLabelProps={{ shrink: true }}
              sx={{ flex: 1 }}
            />
          </div>

          {monedaDistinta && (() => {
            // Calcular diferencia de cambio si hay TC sistema y TC banco
            const tcBanco = tc > 0 && montoDestino > 0
              ? (origenEsPYG ? form.monto / montoDestino : montoDestino / form.monto)
              : 0;
            const difMonto = tcSistema && tc > 0 && montoDestino > 0
              ? Math.round(Math.abs(tcSistema - tcBanco) * (origenEsPYG ? montoDestino : form.monto))
              : 0;
            const esGanancia = tcSistema && tcBanco > 0 && (origenEsPYG ? tcBanco < tcSistema : tcBanco > tcSistema);

            return (
              <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
                {/* Con separador de miles como todo monto: con un campo numérico común
                    "6.150" quedaba en 6,15 y se acreditaba mil veces más (DOBA, oct-2026). */}
                <MonedaInput
                  size="small"
                  label={`Tipo de cambio del banco * — 1 ${monedaExtranjera} = Gs. ?`}
                  moneda="PYG"
                  decimales={2}
                  allowPygDecimals
                  puntoComoMiles
                  placeholder="Ej: 6.150"
                  value={tc}
                  onChange={(v) => setForm((f) => ({ ...f, tipo_cambio: v }))}
                  fullWidth
                  error={tcLejos}
                  helperText={
                    tcLejos
                      ? `Muy lejos de la cotización del día (${fmtMonto(tcSistema, "PYG")}). Revisá que no falte o sobre un cero.`
                      : tc > 0 && form.monto > 0
                        ? `Se acreditarán ${fmtMonto(montoDestino, cuentaDestino?.moneda)} en la cuenta destino`
                        : `Ingresá la cotización que aplicó el banco (ej: 1 ${monedaExtranjera} = Gs. 7.000)`
                  }
                />
                {/* Referencia del sistema */}
                <TcInfoBox $tipo={difMonto > 0 ? (esGanancia ? "ganancia" : "perdida") : "neutral"}>
                  {tcSistema !== null ? (
                    <>
                      <TcInfoRow>
                        <span>TC referencia (Contabilidad):</span>
                        <strong>Gs. {tcSistema.toLocaleString("es-PY")}</strong>
                      </TcInfoRow>
                      {tc > 0 && difMonto > 0 && (
                        <TcInfoRow $resaltado>
                          <span>Diferencia de cambio:</span>
                          <strong style={{ color: esGanancia ? "#22c55e" : "#ef4444" }}>
                            {esGanancia ? "▲ Ganancia" : "▼ Pérdida"} Gs. {difMonto.toLocaleString("es-PY")}
                          </strong>
                        </TcInfoRow>
                      )}
                      {tc > 0 && difMonto > 0 && (
                        <TcInfoNote>
                          Se generará un asiento de 3 líneas con la diferencia de cambio registrada.
                        </TcInfoNote>
                      )}
                    </>
                  ) : (
                    <TcInfoNote $muted>
                      Sin TC registrado en Contabilidad para esta fecha — no se calculará diferencia de cambio.
                    </TcInfoNote>
                  )}
                </TcInfoBox>
              </div>
            );
          })()}

          <TextField
            size="small"
            label="Descripción / Motivo"
            value={form.descripcion}
            onChange={(e) => setForm((f) => ({ ...f, descripcion: e.target.value }))}
            fullWidth
            placeholder="Ej. Reposición caja chica, pago anticipado a proveedor..."
            helperText="Opcional — aparecerá en el historial de movimientos"
          />

          {form.cuenta_origen_id && form.cuenta_origen_id === form.cuenta_destino_id && (
            <Typography variant="caption" color="error">
              ⚠ La cuenta de origen y destino no pueden ser la misma.
            </Typography>
          )}
        </DialogContent>
        <DialogActions sx={{ px: 3, pb: 2 }}>
          <Button onClick={() => { setOpenNew(false); resetForm(); }}>Cancelar</Button>
          <Button
            variant="contained"
            onClick={handleCrear}
            disabled={!formValid || crearMutation.isPending}
            sx={{ background: "#0ea5e9", "&:hover": { background: "#0284c7" } }}
          >
            {crearMutation.isPending ? <CircularProgress size={18} sx={{ mr: 1 }} /> : null}
            {crearMutation.isPending ? "Registrando..." : "Confirmar Transferencia"}
          </Button>
        </DialogActions>
      </Dialog>

      {/* ── Modal anulación ── */}
      <Dialog open={!!anularTarget} onClose={() => { setAnularTarget(null); setMotivoAnulacion(""); }} maxWidth="xs" fullWidth>
        <DialogTitle sx={{ fontWeight: 700, color: "#ef4444" }}>Anular Transferencia</DialogTitle>
        <DialogContent>
          {anularTarget && (
            <Typography variant="body2" sx={{ mb: 2, color: "text.secondary" }}>
              Se revertirán los saldos de <strong>{anularTarget.cuenta_origen?.nombre}</strong> y{" "}
              <strong>{anularTarget.cuenta_destino?.nombre}</strong>. Esta acción no se puede deshacer.
            </Typography>
          )}
          <TextField
            size="small"
            label="Motivo de anulación *"
            value={motivoAnulacion}
            onChange={(e) => setMotivoAnulacion(e.target.value)}
            fullWidth
            multiline
            rows={2}
            autoFocus
          />
        </DialogContent>
        <DialogActions sx={{ px: 3, pb: 2 }}>
          <Button onClick={() => { setAnularTarget(null); setMotivoAnulacion(""); }}>Cancelar</Button>
          <Button
            variant="contained"
            color="error"
            onClick={handleAnular}
            disabled={!motivoAnulacion.trim() || anularMutation.isPending}
          >
            {anularMutation.isPending ? <CircularProgress size={18} sx={{ mr: 1 }} /> : null}
            {anularMutation.isPending ? "Anulando..." : "Confirmar anulación"}
          </Button>
        </DialogActions>
      </Dialog>
    </Container>
  );
}

// ─── Styled components (theme-aware) ────────────────────────────────────────

const Container = styled.div`
  display: flex;
  flex-direction: column;
  gap: 12px;
  height: 100%;
  overflow-y: auto;
`;

const FiltersBar = styled.div`
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
`;

const TableWrap = styled.div`
  background: ${({ theme }) => theme.bg2};
  border: 1px solid ${({ theme }) => theme.color2};
  border-radius: 10px;
  overflow-x: auto;
  @media (max-width: 700px) { display: none; }
`;

const Th = styled.th`
  background: ${({ theme }) => theme.bg3};
  color: ${({ theme }) => theme.textSecondary};
  padding: 10px 12px;
  text-align: left;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  border-bottom: 1px solid ${({ theme }) => theme.color2};
  white-space: nowrap;
`;

const Td = styled.td`
  padding: 10px 12px;
  border-bottom: 1px solid ${({ theme }) => theme.color2};
  font-size: 13px;
  color: ${({ theme }) => theme.text};
  vertical-align: middle;
`;

const AccionesFila = styled.div`
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
`;

const Tr = styled.tr`
  &:last-child td { border-bottom: none; }
  &:hover { background: ${({ theme }) => theme.bg3}; }
`;

const Pagination = styled.div`
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  padding: 10px 16px;
  border-top: 1px solid ${({ theme }) => theme.color2};
`;

const CuentaCell = styled.div`
  display: flex;
  align-items: center;
  gap: 6px;
`;

const MonedaBadge = styled.span`
  font-size: 10px;
  font-weight: 700;
  padding: 1px 5px;
  border-radius: 4px;
  background: ${({ theme }) => theme.bg4};
  color: ${({ theme }) => theme.textSecondary};
`;

const MontoEgreso = styled.span`
  font-weight: 700;
  color: #ef4444;
`;

const MontoIngreso = styled.span`
  font-weight: 700;
  color: #22c55e;
`;

/* ── Mobile ── */
const CardList = styled.div`
  display: none;
  flex-direction: column;
  gap: 10px;
  @media (max-width: 700px) { display: flex; }
`;

/* ── TC Sistema info box ── */
const TcInfoBox = styled.div`
  background: ${({ theme, $tipo }) =>
    $tipo === "ganancia" ? "#22c55e12" :
    $tipo === "perdida"  ? "#ef444412" : theme.bg3 || theme.bg2};
  border: 1px solid ${({ theme, $tipo }) =>
    $tipo === "ganancia" ? "#22c55e44" :
    $tipo === "perdida"  ? "#ef444444" : theme.color2};
  border-radius: 8px;
  padding: 10px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
`;

const TcInfoRow = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  opacity: ${({ $resaltado }) => $resaltado ? 1 : 0.8};
`;

const TcInfoNote = styled.div`
  font-size: 11px;
  opacity: ${({ $muted }) => $muted ? 0.5 : 0.7};
  margin-top: 2px;
  font-style: italic;
`;

const MobCard = styled.div`
  background: ${({ theme }) => theme.bg2};
  border: 1px solid ${({ theme }) => theme.color2};
  border-radius: 10px;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
`;

const MobCardTop = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
`;

const MobFecha = styled.span`
  font-size: 12px;
  color: ${({ theme }) => theme.textSecondary};
`;

const MobFlow = styled.div`
  display: flex;
  align-items: center;
  gap: 8px;
`;

const MobCuenta = styled.div`
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
`;

const MobCuentaLabel = styled.span`
  font-size: 9px;
  font-weight: 700;
  color: ${({ theme }) => theme.textSecondary};
  letter-spacing: 0.5px;
`;

const MobCuentaNombre = styled.span`
  font-size: 13px;
  font-weight: 600;
  color: ${({ theme }) => theme.text};
`;

const MobArrow = styled.div`
  color: ${({ theme }) => theme.textSecondary};
  font-size: 18px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
`;

const MobDesc = styled.div`
  font-size: 12px;
  color: ${({ theme }) => theme.textSecondary};
  font-style: italic;
`;

const EmptyMsg = styled.div`
  text-align: center;
  padding: 40px;
  opacity: 0.5;
  font-size: 14px;
  color: ${({ theme }) => theme.text};
`;
