import { Icon } from "@iconify/react";
import { Alert, Box, IconButton, Tooltip, Typography } from "@mui/material";
import { useEffect, useMemo, useState } from "react";
import { toast } from "sonner";
import {
  actualizarDesvinculacion,
  anularDesvinculacion,
  aprobarDesvinculacion,
  crearDesvinculacion,
  getDesvinculaciones,
  getDesvinculacion,
  getEmpleados,
  pagarDesvinculacion,
  previewDesvinculacion,
} 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 { RRHHGuia } from "./_shared/RRHHGuia";
import { RRHHPrereqChecklist } from "./_shared/RRHHPrereqChecklist";
import { InlineValidationBanner } from "./_shared/InlineValidationBanner";
import { MonedaInput } from "../common/MonedaInput";
import { hoyISO } from "../../utils/fecha";

const TIPO_OPTIONS = [
  { id: "RENUNCIA", label: "Renuncia" },
  { id: "DESPIDO_JUSTIFICADO", label: "Despido justificado (causal)" },
  { id: "DESPIDO_INJUSTIFICADO", label: "Despido injustificado" },
  { id: "MUTUO_ACUERDO", label: "Mutuo acuerdo" },
  { id: "JUBILACION", label: "Jubilación" },
  { id: "FALLECIMIENTO", label: "Fallecimiento" },
  { id: "ABANDONO", label: "Abandono" },
  { id: "FIN_CONTRATO", label: "Fin de contrato" },
];
const ESTADO_OPTIONS = [
  { id: "CALCULADO", label: "Calculado" },
  { id: "APROBADO", label: "Aprobado" },
  { id: "PAGADO", label: "Pagado" },
  { id: "ANULADO", label: "Anulado" },
];
const PREAVISO_OPTIONS = [
  { id: "true", label: "Sí — la empresa NO cumplió el preaviso (se paga)" },
  { id: "false", label: "No — preaviso cumplido (no se paga)" },
];

const empleadoOptionLabel = (e) => `${e.numero_empleado} — ${e.apellidos}, ${e.nombres}`;
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 todayYmd = () => hoyISO();

const buildEmptyCalc = () => ({
  empleado_id: "",
  tipo_desvinculacion: "RENUNCIA",
  fecha_ultimo_dia: todayYmd(),
  fecha_comunicacion: todayYmd(),
  preaviso_omitido: "false",
  salario_pendiente_override: 0,
  dias_vacaciones_no_gozadas: "",
  aguinaldo_proporcional_override: 0,
});

export function DesvinculacionesTab() {
  const { confirm, prompt, dialogs } = useConfirmDialog();

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

  const [empleados, setEmpleados] = useState([]);
  // Cuentas de tesorería en PYG (vacío si la empresa no usa Tesorería).
  const [tesCuentas, setTesCuentas] = useState([]);
  const [pagarCuentaId, setPagarCuentaId] = useState("");

  // Wizard: nueva desvinculación
  const [showWizard, setShowWizard] = useState(false);
  const [calcForm, setCalcForm] = useState(buildEmptyCalc);
  const [erroresCalc, setErroresCalc] = useState([]);
  const [preview, setPreview] = useState(null);
  const [calculando, setCalculando] = useState(false);
  const [creando, setCreando] = useState(false);

  // Detalle de una desvinculación existente
  const [verDesv, setVerDesv] = useState(null);
  const [verLoading, setVerLoading] = useState(false);
  // Form de ajustes manuales
  const [ajustes, setAjustes] = useState(null);

  const totalPages = useMemo(() => Math.max(1, Math.ceil(total / limit)), [total, limit]);
  const empleadoOptions = useMemo(
    () => empleados.map((e) => ({ id: e.id, label: empleadoOptionLabel(e) })),
    [empleados],
  );
  const usaTesoreria = tesCuentas.length > 0;
  const cuentaTesoreriaOptions = tesCuentas.map((c) => ({ id: c.id, label: `${c.nombre} · PYG` }));

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

  useEffect(() => {
    getEmpleados({ page: 1, limit: 200 })
      .then((resp) => setEmpleados(resp?.data || []))
      .catch(() => toast.error("No se pudieron cargar empleados"));
    // Cuentas de tesorería PYG: best-effort (la empresa puede no tener el módulo).
    getTesCuentas({ activo: true })
      .then((cuentas) => {
        const lista = Array.isArray(cuentas) ? cuentas : cuentas?.data || [];
        setTesCuentas(lista.filter((c) => c.activo !== false && c.moneda === "PYG"));
      })
      .catch(() => setTesCuentas([]));
  }, []);
  useEffect(() => { load(); /* eslint-disable-next-line */ }, [page, limit, estadoFiltro]);

  const updateCalc = (k, v) => {
    setCalcForm((p) => ({ ...p, [k]: v }));
    setPreview(null);
  };

  const handleAbrirWizard = () => {
    setCalcForm(buildEmptyCalc());
    setPreview(null);
    setErroresCalc([]);
    setShowWizard(true);
  };

  const handleCalcular = async () => {
    const errs = [];
    if (!calcForm.empleado_id) errs.push({ campo: "Empleado", mensaje: "Elegí el empleado a desvincular" });
    if (!calcForm.fecha_ultimo_dia) errs.push({ campo: "Fecha último día", mensaje: "Indicá la fecha del último día trabajado" });
    if (errs.length) { setErroresCalc(errs); return; }
    setErroresCalc([]);
    try {
      setCalculando(true);
      const resp = await previewDesvinculacion({
        empleado_id: calcForm.empleado_id,
        tipo_desvinculacion: calcForm.tipo_desvinculacion,
        fecha_ultimo_dia: calcForm.fecha_ultimo_dia,
        fecha_comunicacion: calcForm.fecha_comunicacion || undefined,
        preaviso_omitido: calcForm.preaviso_omitido,
        salario_pendiente_override: calcForm.salario_pendiente_override > 0 ? calcForm.salario_pendiente_override : undefined,
        dias_vacaciones_no_gozadas: calcForm.dias_vacaciones_no_gozadas !== "" ? Number(calcForm.dias_vacaciones_no_gozadas) : undefined,
        aguinaldo_proporcional_override: calcForm.aguinaldo_proporcional_override > 0 ? calcForm.aguinaldo_proporcional_override : undefined,
      });
      setPreview(resp);
    } catch (error) {
      toast.error(error?.response?.data?.message || "No se pudo calcular");
    } finally {
      setCalculando(false);
    }
  };

  const handleCrearDesdePreview = async () => {
    if (!preview) return;
    try {
      setCreando(true);
      const desv = await crearDesvinculacion({
        empleado_id: calcForm.empleado_id,
        tipo_desvinculacion: calcForm.tipo_desvinculacion,
        fecha_ultimo_dia: calcForm.fecha_ultimo_dia,
        fecha_comunicacion: calcForm.fecha_comunicacion || undefined,
        preaviso_omitido: calcForm.preaviso_omitido,
        salario_pendiente_override: calcForm.salario_pendiente_override > 0 ? calcForm.salario_pendiente_override : undefined,
        dias_vacaciones_no_gozadas: calcForm.dias_vacaciones_no_gozadas !== "" ? Number(calcForm.dias_vacaciones_no_gozadas) : undefined,
        aguinaldo_proporcional_override: calcForm.aguinaldo_proporcional_override > 0 ? calcForm.aguinaldo_proporcional_override : undefined,
      });
      toast.success("Desvinculación creada en CALCULADO");
      setShowWizard(false);
      setPreview(null);
      await load();
      abrirDetalle(desv.id);
    } catch (error) {
      toast.error(error?.response?.data?.message || "No se pudo crear");
    } finally {
      setCreando(false);
    }
  };

  const abrirDetalle = async (id) => {
    setVerLoading(true);
    try {
      const desv = await getDesvinculacion(id);
      setVerDesv(desv);
      // Cuenta para pagar: la del finiquito o, si hay una sola PYG, esa.
      setPagarCuentaId(desv.cuenta_tesoreria_id || (tesCuentas.length === 1 ? tesCuentas[0].id : ""));
      setAjustes({
        salario_pendiente: Number(desv.salario_pendiente),
        monto_vacaciones_proporcional: Number(desv.monto_vacaciones_proporcional),
        monto_vacaciones_no_gozadas: Number(desv.monto_vacaciones_no_gozadas),
        aguinaldo_proporcional: Number(desv.aguinaldo_proporcional),
        monto_preaviso: Number(desv.monto_preaviso),
        monto_indemnizacion: Number(desv.monto_indemnizacion),
        otros_haberes: Number(desv.otros_haberes),
        otros_descuentos: Number(desv.otros_descuentos),
        consumo_descontado: Number(desv.consumo_descontado || 0),
      });
    } catch {
      toast.error("No se pudo cargar la desvinculación");
      setVerDesv(null);
    } finally {
      setVerLoading(false);
    }
  };
  const recargarDetalle = async () => {
    if (!verDesv) return;
    const desv = await getDesvinculacion(verDesv.id);
    setVerDesv(desv);
    setAjustes({
      salario_pendiente: Number(desv.salario_pendiente),
      monto_vacaciones_proporcional: Number(desv.monto_vacaciones_proporcional),
      monto_vacaciones_no_gozadas: Number(desv.monto_vacaciones_no_gozadas),
      aguinaldo_proporcional: Number(desv.aguinaldo_proporcional),
      monto_preaviso: Number(desv.monto_preaviso),
      monto_indemnizacion: Number(desv.monto_indemnizacion),
      otros_haberes: Number(desv.otros_haberes),
      otros_descuentos: Number(desv.otros_descuentos),
      consumo_descontado: Number(desv.consumo_descontado || 0),
    });
  };
  const cerrarDetalle = () => { setVerDesv(null); setAjustes(null); load(); };

  const handleGuardarAjustes = async () => {
    if (!verDesv) return;
    try {
      await actualizarDesvinculacion(verDesv.id, {
        salario_pendiente: Number(ajustes.salario_pendiente) || 0,
        monto_vacaciones_proporcional: Number(ajustes.monto_vacaciones_proporcional) || 0,
        monto_vacaciones_no_gozadas: Number(ajustes.monto_vacaciones_no_gozadas) || 0,
        aguinaldo_proporcional: Number(ajustes.aguinaldo_proporcional) || 0,
        monto_preaviso: Number(ajustes.monto_preaviso) || 0,
        monto_indemnizacion: Number(ajustes.monto_indemnizacion) || 0,
        otros_haberes: Number(ajustes.otros_haberes) || 0,
        otros_descuentos: Number(ajustes.otros_descuentos) || 0,
        consumo_descontado: Number(ajustes.consumo_descontado) || 0,
      });
      toast.success("Ajustes guardados");
      await recargarDetalle();
    } catch (error) {
      toast.error(error?.response?.data?.message || "No se pudieron guardar los ajustes");
    }
  };

  const handleAprobar = async (desv) => {
    const ok = await confirm({
      title: "Aprobar finiquito",
      message: `Pasará a estado APROBADO. Total: Gs. ${fmtMonto(desv.total_liquidacion_final)}`,
      confirmText: "Aprobar",
      confirmColor: "primary",
    });
    if (!ok) return;
    try {
      await aprobarDesvinculacion(desv.id);
      toast.success("Aprobado");
      if (verDesv?.id === desv.id) await recargarDetalle();
      else load();
    } catch (error) {
      toast.error(error?.response?.data?.message || "No se pudo aprobar");
    }
  };

  const handlePagar = async (desv, cuentaTesoreriaId) => {
    // Resolver cuenta: la pasada, la del finiquito, o la única PYG si hay una sola.
    let cuentaId = cuentaTesoreriaId || desv.cuenta_tesoreria_id || "";
    if (usaTesoreria && !cuentaId && tesCuentas.length === 1) cuentaId = tesCuentas[0].id;
    if (usaTesoreria && !cuentaId) {
      return toast.error("Elegí la cuenta de tesorería desde la que se paga (abrí el detalle para seleccionarla).");
    }
    const ok = await confirm({
      title: "Marcar finiquito como pagado",
      message: usaTesoreria
        ? `El empleado quedará EGRESADO con fecha ${fmtFecha(desv.fecha_ultimo_dia)}. Se registrará el egreso en Tesorería (Gs. ${fmtMonto(desv.total_liquidacion_final)}) y el asiento contable desglosado.`
        : `El empleado quedará EGRESADO con fecha ${fmtFecha(desv.fecha_ultimo_dia)} y no podrá incluirse en futuras liquidaciones. Total: Gs. ${fmtMonto(desv.total_liquidacion_final)}`,
      confirmText: "Pagar y dar de baja",
      confirmColor: "success",
    });
    if (!ok) return;
    try {
      await pagarDesvinculacion(desv.id, cuentaId ? { cuenta_tesoreria_id: cuentaId } : {});
      toast.success("Finiquito pagado · empleado dado de baja");
      if (verDesv?.id === desv.id) await recargarDetalle();
      else load();
    } catch (error) {
      toast.error(error?.response?.data?.message || "No se pudo pagar");
    }
  };

  const handleAnular = async (desv) => {
    const comentario = await prompt({
      title: "Anular desvinculación",
      message: `Empleado: ${desv.empleado?.apellidos}, ${desv.empleado?.nombres}.`,
      label: "Motivo",
      placeholder: "Opcional",
      confirmText: "Anular",
      confirmColor: "warning",
    });
    if (comentario === null) return;
    try {
      await anularDesvinculacion(desv.id, comentario ? { comentario } : {});
      toast.success("Desvinculación anulada");
      if (verDesv?.id === desv.id) cerrarDetalle();
      else load();
    } catch (error) {
      toast.error(error?.response?.data?.message || "No se pudo anular");
    }
  };

  // ════════════════════════════════════════════════════════
  // Wizard
  // ════════════════════════════════════════════════════════
  if (showWizard) {
    return (
      <Container>
        <FormPanel>
          <FormHead>
            <SectionTitle><Icon icon="lucide:user-x" /> Nueva desvinculación</SectionTitle>
            <GhostButton onClick={() => setShowWizard(false)}><Icon icon="lucide:x" /> Cerrar</GhostButton>
          </FormHead>
          <Alert severity="info" sx={{ mb: 2 }}>
            El motor aplica las reglas legales paraguayas (CT Art. 87, 91-94, 219, 244). Podés ajustar manualmente cada concepto antes de crear el finiquito.
          </Alert>
          <InlineValidationBanner errores={erroresCalc} titulo="Revisá los siguientes campos" />
          <FieldsGrid $cols={4}>
            <Field $span={2}>
              <label>Empleado *</label>
              <SearchableSelect options={empleadoOptions} value={calcForm.empleado_id}
                onChange={(id) => updateCalc("empleado_id", id || "")}
                placeholder="Buscar empleado..." />
            </Field>
            <Field $span={2}>
              <label>Tipo de desvinculación *</label>
              <SearchableSelect options={TIPO_OPTIONS} value={calcForm.tipo_desvinculacion}
                onChange={(id) => updateCalc("tipo_desvinculacion", id || "RENUNCIA")} clearable={false} />
              <small style={{ opacity: 0.6, fontSize: "0.75rem" }}>El tipo determina si corresponde preaviso, indemnización y qué rubros se calculan</small>
            </Field>
            <Field>
              <label>Fecha último día *</label>
              <input type="date" value={calcForm.fecha_ultimo_dia}
                onChange={(e) => updateCalc("fecha_ultimo_dia", e.target.value)} />
              <small style={{ opacity: 0.6, fontSize: "0.75rem" }}>Último día trabajado — define antigüedad y base de cálculo de todos los conceptos</small>
            </Field>
            <Field>
              <label>Fecha de comunicación</label>
              <input type="date" value={calcForm.fecha_comunicacion}
                onChange={(e) => updateCalc("fecha_comunicacion", e.target.value)} />
            </Field>
            <Field $span={2}>
              <label>¿Preaviso omitido por la empresa?</label>
              <SearchableSelect options={PREAVISO_OPTIONS} value={calcForm.preaviso_omitido}
                onChange={(id) => updateCalc("preaviso_omitido", id || "false")} clearable={false} />
            </Field>

            <MonedaInput
              label="Salario pendiente override"
              fullWidth
              value={calcForm.salario_pendiente_override}
              onChange={(v) => updateCalc("salario_pendiente_override", v)}
              helperText="Opcional — sobreescribe el cálculo automático de días del último período"
            />
            <Field>
              <label>Días vacaciones no gozadas</label>
              <input type="number" min="0" step="0.5" value={calcForm.dias_vacaciones_no_gozadas}
                onChange={(e) => updateCalc("dias_vacaciones_no_gozadas", e.target.value)}
                placeholder="Auto desde saldo año anterior" />
            </Field>
            <MonedaInput
              label="Aguinaldo proporcional override"
              fullWidth
              sx={{ gridColumn: "span 2" }}
              value={calcForm.aguinaldo_proporcional_override}
              onChange={(v) => updateCalc("aguinaldo_proporcional_override", v)}
              helperText="Opcional — por defecto: salario × meses trabajados en el año ÷ 12"
            />
          </FieldsGrid>

          <Footer>
            <FooterActionButton type="button" $variant="danger" onClick={() => setShowWizard(false)}>
              <Icon icon="lucide:x-circle" /> Cancelar
            </FooterActionButton>
            <FooterActionButton type="button" $variant="primary" disabled={calculando} onClick={handleCalcular}>
              <Icon icon="lucide:calculator" /> {calculando ? "Calculando..." : "Calcular preview"}
            </FooterActionButton>
          </Footer>

          {preview && (
            <>
              <Divider />
              <SectionTitle><Icon icon="lucide:scroll-text" /> Desglose calculado</SectionTitle>
              <FieldsGrid $cols={4}>
                <Field><label>Antigüedad</label><input readOnly value={`${preview.anios_antiguedad} años (${preview.meses_fraccion} m)`} /></Field>
                <Field><label>Salario base</label><input readOnly value={fmtMonto(preview.salario_base_calculo)} /></Field>
                <Field><label>Jornal diario</label><input readOnly value={fmtMonto(preview.jornal_diario_calculo)} /></Field>
                <Field><label>Preaviso omitido</label><input readOnly value={preview.preaviso_omitido ? "Sí (se paga)" : "No"} /></Field>

                <Field><label>Salario pendiente</label><input readOnly value={fmtMonto(preview.salario_pendiente)} /></Field>
                <Field><label>Vac. proporcional ({preview.dias_vacaciones_proporcional} d)</label><input readOnly value={fmtMonto(preview.monto_vacaciones_proporcional)} /></Field>
                <Field><label>Vac. no gozadas ({preview.dias_vacaciones_no_gozadas} d)</label><input readOnly value={fmtMonto(preview.monto_vacaciones_no_gozadas)} /></Field>
                <Field><label>Aguinaldo proporcional</label><input readOnly value={fmtMonto(preview.aguinaldo_proporcional)} /></Field>

                <Field><label>Preaviso ({preview.dias_preaviso} días)</label><input readOnly value={fmtMonto(preview.monto_preaviso)} /></Field>
                <Field><label>Indemnización ({preview.anios_indemnizacion} años × 15 d)</label><input readOnly value={fmtMonto(preview.monto_indemnizacion)} /></Field>
                {Number(preview.consumo_descontado) > 0 && (
                  <Field $span={2}>
                    <label>Consumo de funcionario (−)</label>
                    <input readOnly value={fmtMonto(preview.consumo_descontado)}
                      title="Facturas a crédito pendientes del funcionario. Se descuentan del finiquito y al pagarlo se emite el recibo que las cancela." />
                  </Field>
                )}
                <Field $span={2}>
                  <label style={{ fontWeight: 700, color: "#075985" }}>TOTAL FINIQUITO</label>
                  <input readOnly value={`Gs. ${fmtMonto(preview.total_liquidacion_final)}`}
                    style={{ fontWeight: 700, color: "#075985" }} />
                </Field>
              </FieldsGrid>

              <Footer>
                <FooterActionButton type="button" $variant="primary" disabled={creando} onClick={handleCrearDesdePreview}>
                  <Icon icon="lucide:check-circle" /> {creando ? "Creando..." : "Crear finiquito"}
                </FooterActionButton>
              </Footer>
            </>
          )}
        </FormPanel>
        {dialogs}
      </Container>
    );
  }

  // ════════════════════════════════════════════════════════
  // Detalle
  // ════════════════════════════════════════════════════════
  if (verDesv) {
    const desv = verDesv;
    const emp = desv.empleado || {};
    const esCalculado = desv.estado === "CALCULADO";
    const esAprobado = desv.estado === "APROBADO";
    const puedePagar = esCalculado || esAprobado;
    const puedeAnular = desv.estado !== "PAGADO" && desv.estado !== "ANULADO";

    const updateAj = (k, v) => setAjustes((p) => ({ ...p, [k]: v }));
    const totalEditado =
      Number(ajustes?.salario_pendiente || 0) +
      Number(ajustes?.monto_vacaciones_proporcional || 0) +
      Number(ajustes?.monto_vacaciones_no_gozadas || 0) +
      Number(ajustes?.aguinaldo_proporcional || 0) +
      Number(ajustes?.monto_preaviso || 0) +
      Number(ajustes?.monto_indemnizacion || 0) +
      Number(ajustes?.otros_haberes || 0) -
      Number(ajustes?.otros_descuentos || 0) -
      Number(ajustes?.consumo_descontado || 0);

    return (
      <Container>
        <FormPanel>
          <FormHead>
            <SectionTitle>
              <Icon icon="lucide:user-x" /> Finiquito · {emp.apellidos}, {emp.nombres}
              {" "}<Badge $state={desv.estado}>{desv.estado}</Badge>
            </SectionTitle>
            <Box sx={{ display: "flex", gap: 0.5 }}>
              {esCalculado && (
                <GhostButton onClick={() => handleAprobar(desv)}>
                  <Icon icon="lucide:check-circle" /> Aprobar
                </GhostButton>
              )}
              {puedePagar && (
                <FooterActionButton type="button" $variant="primary" onClick={() => handlePagar(desv, pagarCuentaId)}>
                  <Icon icon="lucide:dollar-sign" /> Pagar y dar de baja
                </FooterActionButton>
              )}
              {puedeAnular && (
                <GhostButton onClick={() => handleAnular(desv)}>
                  <Icon icon="lucide:ban" /> Anular
                </GhostButton>
              )}
              <GhostButton onClick={cerrarDetalle}><Icon icon="lucide:arrow-left" /> Volver</GhostButton>
            </Box>
          </FormHead>

          {puedePagar && usaTesoreria && (
            <Box sx={{ mb: 1.5 }}>
              <FieldsGrid $cols={4}>
                <Field $span={2}>
                  <label>Cuenta de tesorería (pago del finiquito) *</label>
                  <SearchableSelect options={cuentaTesoreriaOptions} value={pagarCuentaId}
                    onChange={(id) => setPagarCuentaId(id || "")}
                    placeholder="Desde qué cuenta se paga…" />
                  <Typography variant="caption" color="text.disabled">
                    Al pagar se registra el egreso en Tesorería desde esta cuenta y el asiento contable desglosado por componente.
                  </Typography>
                </Field>
              </FieldsGrid>
            </Box>
          )}

          <FieldsGrid $cols={4}>
            <Field><label>Empleado</label><input readOnly value={`${emp.numero_empleado || ""} — ${emp.apellidos || ""}, ${emp.nombres || ""}`} /></Field>
            <Field><label>Cédula</label><input readOnly value={emp.cedula_identidad || "—"} /></Field>
            <Field><label>Tipo</label><input readOnly value={desv.tipo_desvinculacion} /></Field>
            <Field><label>Fecha último día</label><input readOnly value={fmtFecha(desv.fecha_ultimo_dia)} /></Field>
            <Field><label>Fecha comunicación</label><input readOnly value={fmtFecha(desv.fecha_comunicacion)} /></Field>
            <Field><label>Antigüedad</label><input readOnly value={`${Number(desv.anios_antiguedad).toFixed(2)} años (${desv.meses_fraccion} m)`} /></Field>
            <Field><label>Salario base</label><input readOnly value={fmtMonto(desv.salario_base_calculo)} /></Field>
            <Field><label>Jornal diario</label><input readOnly value={fmtMonto(desv.jornal_diario_calculo)} /></Field>
          </FieldsGrid>

          <Divider />
          <SectionTitle><Icon icon="lucide:list" /> Conceptos del finiquito {esCalculado ? "(editable)" : ""}</SectionTitle>

          <FieldsGrid $cols={4}>
            <MonedaInput label="Salario pendiente" fullWidth disabled={!esCalculado}
              value={ajustes?.salario_pendiente ?? 0}
              onChange={(v) => updateAj("salario_pendiente", v)} />
            <MonedaInput label={`Vac. proporcional (${Number(desv.dias_vacaciones_proporcional).toFixed(2)} d)`} fullWidth disabled={!esCalculado}
              value={ajustes?.monto_vacaciones_proporcional ?? 0}
              onChange={(v) => updateAj("monto_vacaciones_proporcional", v)} />
            <MonedaInput label={`Vac. no gozadas (${Number(desv.dias_vacaciones_no_gozadas).toFixed(2)} d)`} fullWidth disabled={!esCalculado}
              value={ajustes?.monto_vacaciones_no_gozadas ?? 0}
              onChange={(v) => updateAj("monto_vacaciones_no_gozadas", v)} />
            <MonedaInput label="Aguinaldo proporcional" fullWidth disabled={!esCalculado}
              value={ajustes?.aguinaldo_proporcional ?? 0}
              onChange={(v) => updateAj("aguinaldo_proporcional", v)} />
            <MonedaInput label={`Preaviso (${desv.dias_preaviso} d)`} fullWidth disabled={!esCalculado}
              value={ajustes?.monto_preaviso ?? 0}
              onChange={(v) => updateAj("monto_preaviso", v)} />
            <MonedaInput label={`Indemnización (${desv.anios_indemnizacion} años × 15 d)`} fullWidth disabled={!esCalculado}
              value={ajustes?.monto_indemnizacion ?? 0}
              onChange={(v) => updateAj("monto_indemnizacion", v)} />
            <MonedaInput label="Otros haberes (+)" fullWidth disabled={!esCalculado}
              value={ajustes?.otros_haberes ?? 0}
              onChange={(v) => updateAj("otros_haberes", v)} />
            <MonedaInput label="Otros descuentos (−)" fullWidth disabled={!esCalculado}
              value={ajustes?.otros_descuentos ?? 0}
              onChange={(v) => updateAj("otros_descuentos", v)} />
            {(Number(desv.consumo_descontado) > 0 || Number(ajustes?.consumo_descontado) > 0) && (
              <MonedaInput label="Consumo de funcionario (−)" fullWidth disabled={!esCalculado}
                value={ajustes?.consumo_descontado ?? 0}
                onChange={(v) => updateAj("consumo_descontado", v)}
                helperText={
                  desv.consumo_recibo_id
                    ? "Facturas canceladas con el recibo emitido al pagar."
                    : "Facturas pendientes del funcionario. Al pagar se emite el recibo que las cancela."
                } />
            )}
            <Field $span={4}>
              <label style={{ fontWeight: 700, color: "#075985" }}>TOTAL A PAGAR</label>
              <input readOnly value={`Gs. ${fmtMonto(esCalculado ? totalEditado : desv.total_liquidacion_final)}`}
                style={{ fontWeight: 700, color: "#075985" }} />
            </Field>
          </FieldsGrid>

          {esCalculado && (
            <Footer>
              <FooterActionButton type="button" $variant="primary" onClick={handleGuardarAjustes}>
                <Icon icon="lucide:save" /> Guardar ajustes
              </FooterActionButton>
            </Footer>
          )}
        </FormPanel>
        {dialogs}
      </Container>
    );
  }

  // ════════════════════════════════════════════════════════
  // Listado
  // ════════════════════════════════════════════════════════
  return (
    <Container id="rrhh-desv-list-view">
      <RRHHGuia seccion="desvinculaciones" />
      <RRHHPrereqChecklist tabKey="desvinculaciones" />
      <ListPanel>
        <ListBody>
          <ToolBar id="rrhh-desv-toolbar">
            <Box sx={{ minWidth: 200 }}>
              <SearchableSelect label="Estado" options={ESTADO_OPTIONS} value={estadoFiltro}
                onChange={(id) => { setEstadoFiltro(id || ""); setPage(1); }}
                placeholder="Todos los estados" />
            </Box>
            <Tooltip title="Refrescar">
              <GhostButton onClick={load} disabled={loading}><Icon icon="lucide:refresh-cw" /></GhostButton>
            </Tooltip>
            <Box sx={{ flex: 1 }} />
            <FooterActionButton id="rrhh-desv-new-btn" type="button" $variant="primary" onClick={handleAbrirWizard}>
              <Icon icon="lucide:plus" /> Nueva desvinculación
            </FooterActionButton>
          </ToolBar>

          <div id="rrhh-desv-list-content">
            {loading || verLoading ? (
              <EmptyState>Cargando...</EmptyState>
            ) : data.length === 0 ? (
              <EmptyState>
                <Icon icon="lucide:user-x" width={32} />
                <Typography variant="body2" sx={{ mt: 1, opacity: 0.7 }}>Sin desvinculaciones</Typography>
              </EmptyState>
            ) : (
              <TableWrap id="rrhh-desv-table">
                <table>
                  <thead>
                    <tr>
                      <th>Empleado</th>
                      <th>Tipo</th>
                      <th>Último día</th>
                      <th style={{ textAlign: "center" }}>Antigüedad</th>
                      <th style={{ textAlign: "right" }}>Preaviso</th>
                      <th style={{ textAlign: "right" }}>Indemnización</th>
                      <th style={{ textAlign: "right" }}>Total</th>
                      <th>Estado</th>
                      <th style={{ textAlign: "center" }}>Acciones</th>
                    </tr>
                  </thead>
                  <tbody>
                    {data.map((desv) => {
                      const emp = desv.empleado;
                      const esCalc = desv.estado === "CALCULADO";
                      const esAprob = desv.estado === "APROBADO";
                      return (
                        <tr key={desv.id}>
                          <td>{emp ? `${emp.numero_empleado} — ${emp.apellidos}, ${emp.nombres}` : "-"}</td>
                          <td>{desv.tipo_desvinculacion.replace(/_/g, " ")}</td>
                          <td>{fmtFecha(desv.fecha_ultimo_dia)}</td>
                          <td style={{ textAlign: "center" }}>{Number(desv.anios_antiguedad).toFixed(2)} a</td>
                          <td style={{ textAlign: "right", fontFamily: "monospace" }}>{fmtMonto(desv.monto_preaviso)}</td>
                          <td style={{ textAlign: "right", fontFamily: "monospace" }}>{fmtMonto(desv.monto_indemnizacion)}</td>
                          <td style={{ textAlign: "right", fontFamily: "monospace", fontWeight: 600 }}>{fmtMonto(desv.total_liquidacion_final)}</td>
                          <td><Badge $state={desv.estado}>{desv.estado}</Badge></td>
                          <td style={{ textAlign: "center" }}>
                            <RowActions>
                              <Tooltip title="Abrir">
                                <IconButton size="small" onClick={() => abrirDetalle(desv.id)}>
                                  <Icon icon="lucide:eye" width={16} />
                                </IconButton>
                              </Tooltip>
                              {esCalc && (
                                <Tooltip title="Aprobar">
                                  <IconButton size="small" color="info" onClick={() => handleAprobar(desv)}>
                                    <Icon icon="lucide:check-circle" width={16} />
                                  </IconButton>
                                </Tooltip>
                              )}
                              {(esCalc || esAprob) && (
                                <Tooltip title="Pagar y dar de baja">
                                  <IconButton size="small" color="success" onClick={() => handlePagar(desv)}>
                                    <Icon icon="lucide:dollar-sign" width={16} />
                                  </IconButton>
                                </Tooltip>
                              )}
                              {desv.estado !== "PAGADO" && desv.estado !== "ANULADO" && (
                                <Tooltip title="Anular">
                                  <IconButton size="small" color="error" onClick={() => handleAnular(desv)}>
                                    <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="desvinculaciones"
            rowsPerPage={limit}
            onRowsPerPageChange={(n) => {
              setLimit(n);
              setPage(1);
            }}
          />
        </ListBody>
      </ListPanel>
      {dialogs}
    </Container>
  );
}
