/**
 * Qué sincroniza el job automático con SIFEN.
 *
 * Declarativo a propósito: antes cada tipo se sincronizaba con código suelto y
 * faltaba una combinación —el ESTADO de las notas de remisión— sin que nada lo
 * delatara. Las remisiones quedaban en "Enviado" hasta que alguien apretaba
 * "Sincronizar SIFEN" a mano en la pantalla.
 */

export type TipoDocumentoSifen = 'factura' | 'nota_credito' | 'nota_remision';
export type ModoSync = 'documento' | 'evento';

export interface TareaSync {
  tipo: TipoDocumentoSifen;
  modo: ModoSync;
  /** Tabla Prisma donde buscar empresas con algo pendiente. */
  tabla: 'factura_cab' | 'nota_credito_cab' | 'nota_remision_cab';
  /** Condición de "pendiente de sincronizar". */
  where: Record<string, unknown>;
  etiqueta: string;
}

/** Documento enviado a SIFEN cuyo estado todavía no es definitivo. */
const DOC_PENDIENTE = {
  nro_lote: { not: null },
  estado_sifen: { in: ['Enviado', 'Pendiente', 'Documento firmado'] },
};

/**
 * Evento (cancelación, inutilización) que todavía no se resolvió a favor.
 *
 * Incluye los 'Rechazado' a propósito. Antes el filtro era sólo 'Pendiente' y un
 * rechazo salía para siempre del set de reintentos: la factura 001-001-0002374
 * de DOBA quedó así, con el evento marcado Rechazado por un 4003 ("el CDC ya
 * tiene ese evento") que en realidad confirmaba la cancelación. Nadie la volvió
 * a mirar nunca. Reconsultar un rechazo es barato y idempotente: si SIFEN sigue
 * diciendo que no, queda igual.
 */
const EVENTO_PENDIENTE = {
  evento_aplicado: { in: ['ECAN', 'EINO', 'EINU'] },
  estado_evento: { in: ['Pendiente', 'Rechazado'] },
};

export const TAREAS_SYNC_SIFEN: readonly TareaSync[] = [
  { tipo: 'factura', modo: 'documento', tabla: 'factura_cab', where: DOC_PENDIENTE, etiqueta: 'facturas' },
  { tipo: 'factura', modo: 'evento', tabla: 'factura_cab', where: EVENTO_PENDIENTE, etiqueta: 'eventos de facturas' },
  { tipo: 'nota_credito', modo: 'documento', tabla: 'nota_credito_cab', where: DOC_PENDIENTE, etiqueta: 'notas de crédito' },
  { tipo: 'nota_credito', modo: 'evento', tabla: 'nota_credito_cab', where: EVENTO_PENDIENTE, etiqueta: 'eventos de notas de crédito' },
  { tipo: 'nota_remision', modo: 'documento', tabla: 'nota_remision_cab', where: DOC_PENDIENTE, etiqueta: 'notas de remisión' },
  { tipo: 'nota_remision', modo: 'evento', tabla: 'nota_remision_cab', where: EVENTO_PENDIENTE, etiqueta: 'eventos de notas de remisión' },
];

/**
 * Resuelve, para cada tarea, qué empresas tienen documentos pendientes. El
 * buscador se inyecta para poder probar el plan sin base de datos.
 */
export async function tareasPendientesPorTipo(
  empresasCon: (tarea: TareaSync) => Promise<string[]>,
): Promise<Array<{ tarea: TareaSync; empresaIds: string[] }>> {
  const salida: Array<{ tarea: TareaSync; empresaIds: string[] }> = [];
  for (const tarea of TAREAS_SYNC_SIFEN) {
    const empresaIds = await empresasCon(tarea);
    if (empresaIds.length > 0) salida.push({ tarea, empresaIds });
  }
  return salida;
}
