import type { FilaAlerta, FilaDocumento } from 'src/catalogo/catalogo.service';
import type { AccionCliente, Veredicto } from 'src/catalogo/diagnostico/diagnosticar-documento';
import { diagnosticoDeAlerta } from 'src/catalogo/diagnostico/clasificar-mensaje-sifen';
import { NOMBRE_TIPO, TipoDocumento } from 'src/catalogo/tipos-documento';

/**
 * Lo ÚNICO que ve el redactor de un documento (plan §6.3). Se arma en código:
 * sin ids internos, sin tablas, con terceros enmascarados. El diagnóstico
 * completo queda en trazas.respuesta.
 */

export interface Pantalla {
  /** Miga para el texto: "Menú principal › Facturación". Solo nombres verificados del menú. */
  miga: string;
  /** Ruta del frontend del ERP, para el link. */
  ruta: string;
}

const PANTALLA_DOCUMENTO: Record<TipoDocumento, Pantalla> = {
  FACTURA: { miga: 'Menú principal › Facturación', ruta: '/ventas' },
  NOTA_CREDITO: { miga: 'Menú principal › Facturación (notas de crédito)', ruta: '/ventas/notas-credito' },
  NOTA_REMISION: { miga: 'Menú principal › Facturación (remisiones)', ruta: '/ventas' },
};
const PANTALLA_EMPRESA: Pantalla = { miga: 'Menú principal › Configuración', ruta: '/configuracion/empresa' };
const PANTALLA_CONTACTOS: Pantalla = { miga: 'Menú principal › Contactos', ruta: '/clientes' };
const PANTALLA_PRODUCTOS: Pantalla = { miga: 'Menú principal › Productos', ruta: '/configuracion/productos' };

/** Qué tiene que hacer el cliente, en palabras, por acción. */
const QUE_HACER: Record<AccionCliente, string> = {
  esperar: 'No tiene que hacer nada: el sistema lo confirma solo con SIFEN cada pocos minutos.',
  enviar_a_sifen: 'El documento está pendiente de envío: tiene que enviarlo a SIFEN desde la lista de documentos.',
  corregir_y_reenviar: 'Tiene que corregir el dato que indica SIFEN y volver a enviarlo.',
  reenviar: 'No es un dato suyo: puede volver a enviarlo tal cual desde la lista de documentos.',
  renovar_certificado: 'Tiene que renovar o volver a cargar el certificado digital de la empresa.',
  revisar_alerta_evento:
    'En la campana de alertas tiene la alerta de este evento, con las opciones para reenviarlo o liberarlo.',
  cargar_email_receptor: 'El cliente receptor no tiene correo cargado: tiene que cargarlo en su ficha.',
  revisar_config_correo:
    'El servidor de correo de la empresa rechazó el usuario o la contraseña: tiene que revisarlos.',
};

/** Dónde se corrige un rechazo por dato, según de qué habla el mensaje de SIFEN. */
export function pantallaParaCorregir(mensaje: string | null, tipo: TipoDocumento): Pantalla {
  const m = (mensaje ?? '').toLowerCase();
  if (/receptor|ruc del|d[ií]gito verificador|departamento|distrito|ciudad/.test(m)) return PANTALLA_CONTACTOS;
  if (/dgtin|c[oó]digo de barras|producto/.test(m)) return PANTALLA_PRODUCTOS;
  if (/actividad econ[oó]mica|timbrado|establecimiento|emisor/.test(m)) return PANTALLA_EMPRESA;
  return PANTALLA_DOCUMENTO[tipo];
}

function pantallaPara(accion: AccionCliente | undefined, v: Veredicto, tipo: TipoDocumento): Pantalla | null {
  switch (accion) {
    case 'corregir_y_reenviar':
      return pantallaParaCorregir(v.mensaje, tipo);
    case 'reenviar':
    case 'enviar_a_sifen':
      return PANTALLA_DOCUMENTO[tipo];
    case 'renovar_certificado':
    case 'revisar_config_correo':
      return PANTALLA_EMPRESA;
    case 'cargar_email_receptor':
      return PANTALLA_CONTACTOS;
    default:
      return null;
  }
}

const fecha = (d: Date | null) => (d ? new Date(d).toISOString().slice(0, 10) : null);

export function proyectarDocumento(
  codigo: string,
  documento: FilaDocumento,
  veredicto: Veredicto,
  alertas: FilaAlerta[],
) {
  const accion = veredicto.accionCliente;
  const pantalla = pantallaPara(accion, veredicto, documento.tipo);
  return {
    codigo,
    documento: {
      tipo: NOMBRE_TIPO[documento.tipo],
      numero: documento.nro_documento,
      fecha_emision: fecha(documento.fecha_emision),
      estado_sifen: documento.estado_sifen ?? 'sin enviar',
      cdc: documento.cdc,
      ambiente_de_pruebas: veredicto.ambienteTest,
    },
    diagnostico: {
      situacion: veredicto.situacion,
      resultado: veredicto.resultado,
      mensaje_sifen: veredicto.mensaje,
      que_hacer: accion ? QUE_HACER[accion] : null,
      donde: pantalla,
      no_reemitir: veredicto.noReemitir,
      horas_esperando: veredicto.horasEsperando === null ? null : Math.round(veredicto.horasEsperando * 10) / 10,
      requiere_novasis: veredicto.resultado === 'NO_RESUELTO',
    },
    evento: veredicto.evento
      ? {
          tipo: NOMBRE_EVENTO[veredicto.evento.tipo] ?? veredicto.evento.tipo,
          situacion: veredicto.evento.situacion,
          mensaje: veredicto.evento.mensaje,
          que_hacer: veredicto.evento.accionCliente ? QUE_HACER[veredicto.evento.accionCliente] : null,
        }
      : null,
    correo: {
      estado: veredicto.correo.estado,
      que_hacer: veredicto.correo.accionCliente ? QUE_HACER[veredicto.correo.accionCliente] : null,
      donde: veredicto.correo.accionCliente
        ? pantallaPara(veredicto.correo.accionCliente, veredicto, documento.tipo)
        : null,
    },
    alertas: alertas.map(proyectarAlerta),
  };
}

const NOMBRE_EVENTO: Record<string, string> = {
  ECAN: 'cancelación',
  EINU: 'inutilización',
  EINO: 'nominación',
};

export function proyectarAlerta(a: FilaAlerta) {
  const diagnostico = diagnosticoDeAlerta(a.descripcion);
  return {
    titulo: a.titulo,
    descripcion: a.descripcion,
    que_hacer: a.accion_sugerida,
    criticidad: a.criticidad,
    ruta: a.ruta,
    ...(diagnostico ? { diagnostico } : {}),
  };
}
