import { desc, eq, like } from 'drizzle-orm';
import { db } from '@/db';
import { leads, leadPipelineEventos } from '@/db/schema';
import { obtenerLlamada, descargarGrabacion } from '@/lib/voice/retell';

export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';

const ok = (extra: Record<string, unknown> = {}) =>
  new Response(JSON.stringify({ ok: true, ...extra }), {
    status: 200,
    headers: { 'Content-Type': 'application/json' },
  });

// Webhook de Retell (eventos de llamada). Al terminar la llamada (call_analyzed / call_ended)
// releemos la llamada por su call_id desde la API de Retell (dato autoritativo y autenticado con
// nuestra API key, así un webhook falso no puede inyectar datos), guardamos la transcripción real,
// descargamos la grabación a nuestro sistema (lead.audio_url) y dejamos el análisis en el pipeline.
export async function POST(req: Request): Promise<Response> {
  let body: { event?: string; call?: { call_id?: string } } = {};
  try {
    body = await req.json();
  } catch {
    return new Response('bad json', { status: 400 });
  }

  const event = body.event;
  const callId = body.call?.call_id;
  // Solo nos interesa el final de la llamada; respondemos 200 a todo para que Retell no reintente.
  if (!callId || (event !== 'call_analyzed' && event !== 'call_ended')) return ok({ skipped: true });

  const detalle = await obtenerLlamada(callId);
  if (!detalle) return ok({ matched: false, motivo: 'call no encontrada' });

  // Mapeo al lead: por metadata.lead_id; si falta (llamadas sin metadata), fallback al lead más
  // reciente con ese teléfono (últimos 9 dígitos, tolerante a +34/espacios).
  let leadId = detalle.leadId;
  if (!leadId && detalle.toNumber) {
    const dig = detalle.toNumber.replace(/\D/g, '').slice(-9);
    if (dig.length === 9) {
      const [m] = await db
        .select({ id: leads.id })
        .from(leads)
        .where(like(leads.telefono, `%${dig}%`))
        .orderBy(desc(leads.createdAt))
        .limit(1);
      leadId = m?.id ?? null;
    }
  }
  if (!leadId) return ok({ matched: false, motivo: 'sin lead' });

  const [lead] = await db.select({ id: leads.id }).from(leads).where(eq(leads.id, leadId)).limit(1);
  if (!lead) return ok({ matched: false, motivo: 'lead no existe' });

  const audioUrl = detalle.recordingUrl ? await descargarGrabacion(detalle.recordingUrl) : null;

  await db
    .update(leads)
    .set({
      transcripcion: detalle.transcript ?? undefined,
      audioUrl: audioUrl ?? undefined,
      updatedAt: new Date(),
    })
    .where(eq(leads.id, leadId));

  await db.insert(leadPipelineEventos).values({
    leadId,
    stage: 'llamada_completada',
    metadata: {
      via: 'webhook',
      real: true,
      retellCallId: detalle.callId,
      callStatus: detalle.callStatus,
      duracionSeg: detalle.duracionSeg,
      grabacionGuardada: Boolean(audioUrl),
      analysis: detalle.analysis ?? null,
    },
  });

  return ok({ matched: true, leadId, transcript: Boolean(detalle.transcript), grabacion: Boolean(audioUrl) });
}
