// ─── Inventario · Compartido ────────────────────────────────────────────────
// Helpers de dominio de vencimiento/estado de lote que usan TANTO lista.jsx
// (chips/KPIs de vencimiento) COMO detalle.jsx (tabla de Lotes) — extraídos acá
// (P10, split de screens-inventario.jsx en screens/inventario/) para no
// duplicarlos entre los dos scripts (cada `<script type="text/babel">` tiene su
// propio scope, ver AGENTS.md §11 — sin este archivo, detalle.jsx necesitaría
// su propia copia de invLoteEstado/invTiempoRestante).
// Expone a window: invLoteEstado, INV_LOTE_CFG, invTiempoRestante,
// invProxVencimiento, invHasVencido, INV_ESTADO_CFG, INV_CATEGORIAS,
// VAC_ESTADO_CFG, VAC_MOVIMIENTO_CFG, HISTORIAL_EMPTY_TEXT (P24, empty-state
// compartido por detalle.jsx e historial.jsx), vacTamanoDeDescripcion (DECISIÓN 2,
// 06/07/2026 — usado por activo-detalle.jsx para armar el selector "Tipo" del alta).
// Consume window.MicosTodayISO/MS_PER_DAY/INV_VENC_THRESHOLDS (dominio/formato.js,
// core/bundle-config.js).

// "Hoy" para comparar contra `vencimiento` (columna DATE, sin hora — igual que
// `current_date` en Postgres, que corre en UTC: ver v_inventario_stats). `window.MicosNow()`
// trae la hora actual; restarla directo contra `new Date('YYYY-MM-DD')` (que el motor de JS
// parsea como medianoche UTC) hacía que CUALQUIER lote que vence HOY diera diffDays negativo
// ni bien pasaba la medianoche UTC → se pintaba VENCIDO durante todo el día en vez de
// PROXIMO, divergiendo del criterio SQL (`vencimiento < current_date`) — BUGS-caza-
// 01-07-2026.md #27/B3 (verificado en vivo: 5 productos con vencimiento=hoy sumaban al chip
// "Vencidos" del front pero no al KPI "Lotes vencidos" server-side). Normalizamos `hoy` a la
// medianoche UTC del día calendario (mismo string que `MicosTodayISO()`) para que la resta de
// fechas quede en días enteros, igual que la comparación por DATE de Postgres.
function invHoy() { return new Date(window.MicosTodayISO ? window.MicosTodayISO() : new Date().toISOString().slice(0, 10)); }

function invLoteEstado(vencimiento) {
  const hoy = invHoy();
  const venc = new Date(vencimiento);
  const diffDays = (venc - hoy) / (window.MS_PER_DAY || 86400000);
  if (diffDays < 0)  return 'VENCIDO';
  if (diffDays < ((window.INV_VENC_THRESHOLDS || {}).proximoDias || 90)) return 'PROXIMO';
  return 'VIGENTE';
}

const INV_LOTE_CFG = {
  VIGENTE: { label: 'Vigente',      tone: 'pos'  },
  PROXIMO: { label: 'Próx. vencer', tone: 'warn' },
  VENCIDO: { label: 'Vencido',      tone: 'neg'  },
};

function invTiempoRestante(isoDate) {
  if (!isoDate) return { text: '—', tone: 'neutral' };
  const hoy  = invHoy();
  const venc = new Date(isoDate);
  const diffDays = Math.ceil((venc - hoy) / (window.MS_PER_DAY || 86400000));
  if (diffDays < 0) {
    const abs = Math.abs(diffDays);
    if (abs < 31) return { text: `Vencido hace ${abs}d`,                              tone: 'neg' };
    const m = Math.round(abs / 30.5);
    return               { text: `Hace ${m} mes${m === 1 ? '' : 'es'}`,              tone: 'neg' };
  }
  if (diffDays === 0)   return { text: 'Vence hoy',                                   tone: 'neg' };
  if (diffDays < ((window.INV_VENC_THRESHOLDS || {}).criticoDias || 31))    return { text: `En ${diffDays} días`, tone: diffDays < ((window.INV_VENC_THRESHOLDS || {}).urgenteDias || 8) ? 'neg' : 'warn' };
  const m = Math.round(diffDays / 30.5);
  if (m <= 3)           return { text: `En ${m} mes${m === 1 ? '' : 'es'}`,           tone: 'warn' };
  return                       { text: `En ${m} meses`,                               tone: 'neutral' };
}

function invProxVencimiento(lotes) {
  if (!lotes || lotes.length === 0) return null;
  const hoy = invHoy();
  const vigentes = lotes.filter(l => new Date(l.vencimiento) >= hoy)
    .sort((a, b) => new Date(a.vencimiento) - new Date(b.vencimiento));
  if (vigentes.length > 0) return vigentes[0].vencimiento;
  return [...lotes].sort((a, b) => new Date(b.vencimiento) - new Date(a.vencimiento))[0]?.vencimiento || null;
}

function invHasVencido(item) {
  return item.lotes.some(l => invLoteEstado(l.vencimiento) === 'VENCIDO');
}

const INV_ESTADO_CFG = {
  ok:      { label: 'Stock OK',   tone: 'pos'  },
  bajo:    { label: 'Stock bajo', tone: 'warn' },
  critico: { label: 'Crítico',    tone: 'neg'  },
  agotado:  { label: 'Agotado',    tone: 'neg'  },
};

const INV_CATEGORIAS = ['Bolsas', 'Curación', 'Cirugía', 'Ortopedia', 'Oftalmología', 'Ort. y Tornillos'];

// ─── P23 (VACs) — estado REAL de cada equipo + tipo de movimiento de alquiler ──
// Enums de `inventario_activo.estado` / `inventario_alquiler.tipo` (backend, sin
// labelizar — ver src/lib/api/serializers/inventario-activos.ts: el front es dueño de
// la etiqueta/tono, mismo criterio que INV_ESTADO_CFG de arriba). Usados por
// lista.jsx (chips/columna Estado), activo-detalle.jsx e historial-alquileres.jsx.
const VAC_ESTADO_CFG = {
  ESTACIONADO:   { label: 'Estacionado',   tone: 'pos'     },
  ALQUILADO:     { label: 'Alquilado',     tone: 'neutral' },
  EN_REPARACION: { label: 'En reparación', tone: 'warn'    },
  BAJA:          { label: 'Baja',          tone: 'neg'     },
};
const VAC_MOVIMIENTO_CFG = {
  SALIDA:  { label: 'Salida',   tone: 'neg'     }, // sale del depósito (a un paciente o a reparar)
  ENTRADA: { label: 'Entrada',  tone: 'pos'     }, // vuelve al depósito
  DEPO:    { label: 'Depósito', tone: 'neutral' }, // quedó en depósito (sin salida/entrada real)
};

// DECISIÓN 2 (alta de equipos VAC, 06/07/2026): deriva "Chica"/"Mediana"/"Grande" de la
// descripción real del producto `inventario` (ej. "Bomba VAC Chica (terapia de presión
// negativa) — alquiler"), MISMA regla que `tamanoFromDescripcion` en
// src/lib/api/serializers/inventario-activos.ts (gemela a propósito — el backend ya la usa
// para resolver el tamaño de cada EQUIPO en el GET; acá se necesita del lado del cliente
// para armar las 3 opciones de "Tipo" del alta, antes de que el equipo exista). `null` si no
// matchea ninguno (nunca inventa un tamaño).
function vacTamanoDeDescripcion(desc) {
  if (!desc) return null;
  if (/grande/i.test(desc)) return 'Grande';
  if (/median/i.test(desc)) return 'Mediana';
  if (/chica/i.test(desc)) return 'Chica';
  return null;
}

// P24 (03/07/2026 — libro de movimientos): empty-state HONESTO del historial de stock de
// consumibles (detalle.jsx sub-tabla + historial.jsx ledger completo) — antes decía "Sin
// movimientos registrados" a secas, indistinguible de "este producto nunca tuvo movimientos"
// cuando en realidad NINGÚN producto los tenía (inventario_movimiento tenía 0 filas: ningún
// write-path insertaba, ver serializers/inventario-movimientos.ts). Ahora que remitos/
// ajustes/logística/edición manual sí dejan rastro, un producto sin filas acá es honesto —
// pero aclarando que el LIBRO arranca hoy (no hay carga retroactiva de lo viejo).
const HISTORIAL_EMPTY_TEXT = 'Sin movimientos registrados. El libro de movimientos arranca el 03/07/2026 — lo anterior a esa fecha no quedó documentado.';

Object.assign(window, {
  invLoteEstado, INV_LOTE_CFG, invTiempoRestante, invProxVencimiento, invHasVencido,
  INV_ESTADO_CFG, INV_CATEGORIAS, VAC_ESTADO_CFG, VAC_MOVIMIENTO_CFG, HISTORIAL_EMPTY_TEXT,
  vacTamanoDeDescripcion,
});
