/**
 * Expansión léxica de la pregunta del usuario antes de embeddearla.
 *
 * Problema que resuelve: usuarios escriben corto y con abreviaturas
 * ("nc", "anular fc", "alta cli"). Esos términos no aparecen literales en
 * la documentación, así que el embedding del texto crudo se aleja del doc
 * correcto y baja el recall.
 *
 * Solución: si detectamos un término clave de un grupo de sinónimos, lo
 * concatenamos al final de la pregunta como texto adicional. NO reemplazamos
 * — el original sigue presente para preservar la intención original del usuario.
 *
 * Ejemplo:
 *   in:  "como anulo una nc?"
 *   out: "como anulo una nc? [términos relacionados: nota de crédito, anular, cancelar]"
 *
 * El embedding del texto expandido cae más cerca del chunk del doc correcto.
 * El LLM nunca ve esto — solo el embedder. La pregunta cruda igual va al LLM
 * por separado vía el prompt.
 */

interface GrupoSinonimos {
  // Cualquiera de estos términos detectado (como palabra completa) dispara el grupo
  trigger: string[];
  // Términos extra que sumamos al texto a embeddear
  expandir: string[];
}

// Diccionario chico, curado a mano. Crece a medida que vemos preguntas reales
// en la auditoría con `recall_categoria=fallback_debil` o `sin_contexto`.
const GRUPOS: GrupoSinonimos[] = [
  // Facturación / SIFEN
  {
    trigger: ['nc', 'n.c.', 'notacredito'],
    expandir: ['nota de crédito', 'anular factura'],
  },
  {
    trigger: ['fc', 'fact', 'fact.'],
    expandir: ['factura'],
  },
  {
    trigger: ['anular', 'anulación', 'cancelar', 'cancelacion', 'cancelación'],
    expandir: ['nota de crédito', 'evento sifen', 'inutilizar'],
  },
  {
    trigger: ['sifen', 'set'],
    expandir: ['facturación electrónica', 'CDC', 'estado del comprobante'],
  },
  {
    trigger: ['cdc'],
    expandir: ['código de control', 'factura electrónica'],
  },

  // Numeraciones de documentos (se administran dentro del punto de expedición)
  {
    trigger: ['numeracion', 'numeración', 'numeraciones', 'talonario', 'serie de documentos', 'numeracion agotada', 'numeración agotada'],
    expandir: ['numeraciones de documentos', 'punto de expedición', 'sucursales y cajas', 'nueva numeración'],
  },

  // Cobros / créditos
  {
    trigger: ['cobro', 'cobrar', 'recibo'],
    expandir: ['cobro a cliente', 'medios de pago', 'panel cobrador'],
  },
  {
    trigger: ['multi', 'multi recibo', 'multi-recibo', 'multifactura', 'multi factura', 'multi-factura', 'varias facturas'],
    expandir: ['recibo multi-factura', 'aplicar nota de crédito en recibo', 'cobrar varias facturas', 'modos de nota de crédito al cobrar'],
  },
  {
    trigger: ['estira', 'estirar', 'aparece', 'aparezca', 'no aparece', 'no me aparece', 'no se ve', 'no figura'],
    expandir: ['aplicar', 'mostrar', 'listar'],
  },
  {
    trigger: ['credito', 'crédito', 'prestamo', 'préstamo', 'financiacion', 'financiación'],
    expandir: ['solicitud de crédito', 'plan de cuotas', 'cobranza'],
  },
  {
    trigger: ['cuota', 'cuotas'],
    expandir: ['plan de cuotas', 'solicitud de crédito', 'venta a crédito'],
  },

  // Compras / Orden de Pago — flag "incluir contado en orden de pago"
  {
    trigger: [
      'orden de pago',
      'por op',
      'pagada por op',
      'pagado por op',
      'pagar por op',
      'contado en orden',
      'incluir contado',
      'centralizar pagos',
    ],
    expandir: [
      'incluir contado en orden de pago',
      'incluir_contado_en_orden_pago',
      'configuración de compras',
      'que el contado quede pendiente de pago',
      'pagar compras y gastos de contado por orden de pago',
      'centralizar todos los pagos en la orden de pago',
    ],
  },

  // Tesorería / cheques
  {
    trigger: ['cheque', 'cheques'],
    expandir: ['cartera de cheques', 'banco', 'depositar', 'recibir cheque', 'tipo de cheque'],
  },
  {
    trigger: ['diferido', 'diferidos', 'posfechado', 'posfechados', 'pos fechado', 'al dia', 'al día'],
    expandir: ['cheque diferido', 'cheque al día', 'fecha de vencimiento', 'cheque en cartera', 'cheque posfechado'],
  },
  {
    trigger: ['caja', 'arqueo', 'cierre', 'apertura'],
    expandir: ['sesión de caja', 'turno', 'cuadre'],
  },
  {
    trigger: ['banco', 'bancos', 'cta', 'cuenta bancaria'],
    expandir: ['cuenta de tesorería', 'depósito', 'transferencia'],
  },
  {
    trigger: ['transferencia', 'transferencias', 'transferencia bancaria'],
    expandir: [
      'medio de pago transferencia',
      'movimiento de tesorería',
      'categoría de movimiento',
      'cuenta bancaria destino',
      'cobro por transferencia',
      'pago por transferencia',
    ],
  },
  {
    trigger: ['categoria', 'categoría', 'categorias', 'categorías', 'tipo de movimiento', 'tipos de movimiento'],
    expandir: [
      'categoría de movimiento de tesorería',
      'clasificación de ingreso',
      'clasificación de egreso',
      'concepto contable',
      'plan de cuentas',
    ],
  },
  {
    trigger: ['tesoreria', 'tesorería'],
    expandir: [
      'movimiento de tesorería',
      'cuenta de tesorería',
      'ingreso',
      'egreso',
      'transferencia entre cuentas',
      'categoría de movimiento',
    ],
  },

  // Stock
  {
    trigger: ['stock', 'inventario', 'existencia', 'existencias'],
    expandir: ['movimientos de stock', 'depósito', 'ajuste'],
  },
  {
    trigger: ['lote', 'lotes', 'vencimiento'],
    expandir: ['producto por lote', 'fecha de vencimiento'],
  },
  {
    trigger: ['oferta', 'ofertas', 'promo', 'promocion', 'promoción'],
    expandir: ['descuento', 'precio promocional'],
  },

  // Contactos
  {
    trigger: ['cli', 'cliente'],
    expandir: ['alta de cliente', 'datos fiscales', 'lista de precios'],
  },
  {
    trigger: ['prov', 'proveedor'],
    expandir: ['alta de proveedor'],
  },

  // RRHH
  {
    trigger: ['liquidacion', 'liquidación', 'sueldo', 'salario'],
    expandir: ['liquidación quincenal', 'liquidación mensual', 'ips'],
  },
  {
    trigger: ['empleado', 'empleados', 'personal'],
    expandir: ['alta de empleado', 'datos contractuales'],
  },

  // Contabilidad
  {
    trigger: ['asiento', 'asientos', 'contabilidad'],
    expandir: ['libro diario', 'plan de cuentas', 'asiento automático', 'mapeo de cuentas', 'banner contabilidad'],
  },
  {
    trigger: ['no me crea', 'no se crea', 'no genera', 'no se genera', 'falta', 'no aparece'],
    expandir: ['configuración faltante', 'requisitos', 'prerrequisitos'],
  },

  // Métodos de pago / monedas / cotizaciones
  {
    trigger: ['metodo de pago', 'método de pago', 'metodos de pago', 'métodos de pago', 'forma de pago', 'formas de pago', 'medio de pago', 'medios de pago'],
    expandir: ['alta de método de pago', 'configuración de método de pago', 'código SIFEN forma de pago', 'activar método de pago', 'configuración facturación monedas métodos de pago'],
  },
  {
    trigger: ['moneda', 'monedas', 'cotizacion', 'cotización', 'tipo de cambio', 'usd', 'dolar', 'dólar', 'pyg', 'guarani', 'guaraní'],
    expandir: ['cotización compra venta', 'tipo de cambio contable', 'moneda principal', 'configuración de monedas'],
  },

  // Configuración
  {
    trigger: ['configuracion', 'configurar', 'configuración', 'cargar', 'dar de alta', 'agregar', 'crear nuevo'],
    expandir: ['configuración', 'alta', 'mantenimiento'],
  },
];

/**
 * Devuelve la pregunta enriquecida para embedding.
 * Si no hay ningún match, devuelve la pregunta sin tocar.
 */
/**
 * "Nota de crédito" es un documento, no un crédito: sin esto la palabra suelta
 * disparaba el grupo/alias de créditos y "¿cómo creo una numeración para nota
 * de crédito?" recuperaba la guía de Solicitud de Crédito. Se colapsa a
 * `notacredito`, que es trigger del grupo de NC.
 */
export function normalizarNotaCredito(texto: string): string {
  return texto.replace(/notas?\s+de\s+cr[eé]dito/giu, 'notacredito');
}

export function expandirParaEmbedding(pregunta: string): string {
  const lower = normalizarNotaCredito(pregunta.toLowerCase());
  const expansiones = new Set<string>();

  for (const g of GRUPOS) {
    const hit = g.trigger.some((t) => {
      const re = new RegExp(
        `(^|[^\\p{L}\\p{N}])${escapeRegex(t.toLowerCase())}([^\\p{L}\\p{N}]|$)`,
        'iu',
      );
      return re.test(lower);
    });
    if (hit) {
      for (const e of g.expandir) expansiones.add(e);
    }
  }

  if (expansiones.size === 0) return pregunta;
  return `${pregunta} [términos relacionados: ${Array.from(expansiones).join(', ')}]`;
}

function escapeRegex(s: string): string {
  return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
