import { eq } from 'drizzle-orm';
import { db } from '@/db';
import { leads, leadPipelineEventos, tenants } from '@/db/schema';
import { getPricingConfigFor, getCatalogFor, getEnvioModeFor } from '@/db/pricing-queries';
import { computeBudget } from '@/budget';
import type { Lead } from '@/db/schema';
import { deterministicExtractor } from '@/lib/voice/extractor';
import { mergeIntoBudgetInputs, applyPreferences } from '@/lib/voice/apply';
import { iniciarLlamadaSaliente, construirVariablesLlamada } from '@/lib/voice/retell';
import type { RawCallData } from '@/lib/voice/preferences';

// Render demo por tipo de reforma. No hay generación IA real en esta fase (keyless):
// reusamos los renders de muestra del directorio público.
const RENDER_POR_TIPO: Record<NonNullable<Lead['tipoReforma']>, string> = {
  cocina: '/despues.webp',
  bano: '/despues-bano.webp',
  salon: '/despues-comedor.webp',
  comedor: '/despues-comedor.webp',
  integral: '/despues.webp',
  otro: '/despues.webp',
};

const TIPO_TEXTO: Record<NonNullable<Lead['tipoReforma']>, string> = {
  cocina: 'la cocina',
  bano: 'el baño',
  salon: 'el salón',
  comedor: 'el comedor',
  integral: 'el piso entero',
  otro: 'la reforma',
};

function construirTranscripcion(lead: Lead): string {
  const tipo = lead.tipoReforma ?? 'otro';
  const m2 = lead.m2Suelo ? `${Math.round(lead.m2Suelo)} metros` : 'el espacio';
  const calidad = lead.calidadGlobal ?? 'media';
  return [
    `Agente: Hola ${lead.nombre.split(' ')[0]}, te llamo de Reformas Ejemplo. Te aviso de que soy un asistente con inteligencia artificial y de que la llamada queda grabada. ¿Tienes un momento?`,
    `Cliente: Sí, sin problema.`,
    `Agente: Perfecto. Me comentas que quieres reformar ${TIPO_TEXTO[tipo]}, ¿unos ${m2} aproximadamente?`,
    `Cliente: Eso es, ${m2}. Quiero un acabado de calidad ${calidad}.`,
    `Agente: Genial. Con las fotos que has subido y estos datos te preparo ahora mismo el render y el presupuesto orientativo, y te lo enviamos por WhatsApp. Muchas gracias.`,
  ].join('\n');
}

function construirEntidades(lead: Lead) {
  return {
    espacio: lead.tipoReforma ?? 'otro',
    m2_aprox: lead.m2Suelo ?? null,
    calidad: lead.calidadGlobal ?? 'media',
    provincia: lead.provincia ?? null,
    estructural: lead.estructural,
  };
}

// Avanza un lead recién capturado por todo el pipeline B2C.
// Los pasos de IA (pre-llamada, llamada, render) se simulan de forma realista;
// el presupuesto se calcula DE VERDAD con el motor y el catálogo del reformista.
// Respeta la preferencia de envío del reformista: 'automatico' entrega por WhatsApp,
// 'revision' se detiene en 'presupuesto_generado' para que el reformista lo revise.
export async function procesarLead(leadId: string): Promise<void> {
  const [lead] = await db.select().from(leads).where(eq(leads.id, leadId)).limit(1);
  if (!lead) throw new Error('Lead no encontrado.');

  const [tenant] = await db
    .select({ nombreEmpresa: tenants.nombreEmpresa })
    .from(tenants)
    .where(eq(tenants.id, lead.tenantId))
    .limit(1);
  const nombreEmpresa = tenant?.nombreEmpresa ?? 'Reformix';

  const tipo = lead.tipoReforma ?? 'otro';

  // Paso 4: pre-llamada (SMS + WhatsApp)
  await db.insert(leadPipelineEventos).values({
    leadId,
    stage: 'prellamada_enviada',
    metadata: { via: ['sms', 'whatsapp'], simulado: true },
  });

  // Paso 5: llamada del agente IA. Si Retell está configurado se lanza una llamada saliente
  // REAL (el móvil del lead suena y el agente habla con sus variables); el render y el
  // presupuesto se siguen generando con los datos del formulario (Arquitectura A de la demo).
  const llamada = await iniciarLlamadaSaliente({
    telefono: lead.telefono,
    variables: construirVariablesLlamada({ nombreEmpresa }, lead),
    leadId,
  });
  // Si la llamada es REAL, la transcripción real la rellena el webhook de Retell al colgar; no
  // guardamos el placeholder. Solo usamos el transcript simulado cuando no hay llamada real.
  const transcripcion = llamada ? null : construirTranscripcion(lead);
  const entidades = construirEntidades(lead);
  await db.insert(leadPipelineEventos).values({
    leadId,
    stage: 'llamada_completada',
    metadata: {
      simulado: !llamada,
      real: Boolean(llamada),
      retellCallId: llamada?.callId,
      duracionSeg: 95,
    },
  });

  // Paso 6a: render IA generado
  const renderUrl = RENDER_POR_TIPO[tipo];
  await db.insert(leadPipelineEventos).values({
    leadId,
    stage: 'render_generado',
    metadata: { simulado: true, renderUrl },
  });

  // Paso 6b: presupuesto calculado (REAL) con catálogo + preferencias abstraídas
  const [config, catalog] = await Promise.all([
    getPricingConfigFor(lead.tenantId),
    getCatalogFor(lead.tenantId),
  ]);

  const raw: RawCallData = {
    tipoReforma: tipo,
    m2Suelo: lead.m2Suelo ?? null,
    calidad: lead.calidadGlobal ?? null,
    estructural: lead.estructural,
    urgencia: lead.urgencia ?? null,
    presupuestoTarget: lead.presupuestoTarget ?? null,
    tasteText: lead.tasteText ?? '',
  };
  const prefs = deterministicExtractor.extract(raw, catalog);
  const inputs = mergeIntoBudgetInputs(prefs, {
    tipoReforma: lead.tipoReforma,
    m2Suelo: lead.m2Suelo ?? null,
    alturaTecho: lead.alturaTecho ?? null,
    provincia: lead.provincia ?? null,
    anteriorA2000: lead.anteriorA2000,
    cambioDistribucion: lead.cambioDistribucion,
  });
  const result = applyPreferences(computeBudget(inputs, config, catalog), prefs);

  await db
    .update(leads)
    .set({
      transcripcion,
      entidades,
      renderUrl,
      presupuestoEstimado: result.total,
      desgloseSnapshot: { stage: 'presupuesto_generado', result },
      preferencesSnapshot: prefs,
      pipelineStage: 'presupuesto_generado',
      updatedAt: new Date(),
    })
    .where(eq(leads.id, leadId));

  await db.insert(leadPipelineEventos).values({
    leadId,
    stage: 'presupuesto_generado',
    metadata: { total: result.total, confianza: result.confianza },
  });

  // Paso 7: entrega por WhatsApp si el reformista tiene envío automático.
  // NOTA: esto es el estado intermedio del funnel (entrega simulada con el presupuesto
  // orientativo). La entrega REAL con el PDF (email + señal WhatsApp) ocurre en
  // finalizarYEntregar (lib/funnel/finalizar.ts), cuando llegan las imágenes "después".
  const envio = await getEnvioModeFor(lead.tenantId);
  if (envio === 'automatico') {
    await db
      .update(leads)
      .set({
        pipelineStage: 'whatsapp_entregado',
        estado: 'presupuesto_enviado',
        updatedAt: new Date(),
      })
      .where(eq(leads.id, leadId));
    await db.insert(leadPipelineEventos).values({
      leadId,
      stage: 'whatsapp_entregado',
      metadata: { via: 'whatsapp', simulado: true, total: result.total },
    });
  }
}

export { RENDER_POR_TIPO };
