import { env, retellConfigurado } from '@/lib/env';
import { TIPO_LABEL } from '@/lib/funnel';
import type { Lead } from '@/db/schema';

const CREATE_PHONE_CALL_URL = 'https://api.retellai.com/v2/create-phone-call';
const GET_CALL_URL = 'https://api.retellai.com/v2/get-call';

// Normaliza un teléfono español a E.164 (+34XXXXXXXXX), que es lo que exige Retell.
// Acepta espacios, guiones, paréntesis y los prefijos +34 / 0034 / 34 ya puestos.
export function normalizarTelefonoEs(raw: string): string | null {
  const limpio = raw.replace(/[\s\-().]/g, '');
  if (/^\+[1-9]\d{7,14}$/.test(limpio)) return limpio;
  if (/^0034\d{9}$/.test(limpio)) return `+${limpio.slice(2)}`;
  if (/^34\d{9}$/.test(limpio)) return `+${limpio}`;
  if (/^[6789]\d{8}$/.test(limpio)) return `+34${limpio}`;
  return null;
}

export type VariablesLlamada = Record<string, string>;

// Dynamic variables que el agente de Retell inserta en su prompt ({{empresa_nombre}}, etc.).
// Solo los datos que el script "habla": empresa y nombre de pila del cliente; tipo de reforma
// y provincia van como contexto opcional para que el agente confirme en vez de preguntar a frío.
export function construirVariablesLlamada(
  empresa: { nombreEmpresa: string },
  lead: Pick<Lead, 'nombre' | 'tipoReforma' | 'provincia'>,
): VariablesLlamada {
  const vars: VariablesLlamada = {
    empresa_nombre: empresa.nombreEmpresa,
    cliente_nombre: lead.nombre.split(' ')[0],
  };
  if (lead.tipoReforma) vars.tipo_reforma = TIPO_LABEL[lead.tipoReforma].toLowerCase();
  if (lead.provincia) vars.provincia = lead.provincia;
  return vars;
}

export type ResultadoLlamada = { callId: string };

// Inicia una llamada saliente con el agente de Retell. Best-effort para la demo (Arquitectura A):
// el POST vuelve en cuanto Retell acepta la llamada (el móvil del lead empieza a sonar) y el
// pipeline continúa generando el entregable. Si Retell no está configurado, el teléfono no es
// válido o la API falla, devuelve null y NO lanza — el funnel sigue en modo simulado.
export async function iniciarLlamadaSaliente(opts: {
  telefono: string;
  variables: VariablesLlamada;
  leadId?: string; // se manda como metadata.lead_id para mapear la llamada al lead en el webhook
}): Promise<ResultadoLlamada | null> {
  if (!retellConfigurado()) return null;

  const toNumber = normalizarTelefonoEs(opts.telefono);
  if (!toNumber) return null;

  const body: Record<string, unknown> = {
    from_number: env.RETELL_FROM_NUMBER,
    to_number: toNumber,
    retell_llm_dynamic_variables: opts.variables,
  };
  if (opts.leadId) body.metadata = { lead_id: opts.leadId };
  if (env.RETELL_AGENT_ID) body.override_agent_id = env.RETELL_AGENT_ID;

  try {
    const res = await fetch(CREATE_PHONE_CALL_URL, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${env.RETELL_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(body),
    });
    if (!res.ok) {
      console.error(`Retell create-phone-call ${res.status}: ${await res.text()}`);
      return null;
    }
    const data = (await res.json()) as { call_id?: string };
    return data.call_id ? { callId: data.call_id } : null;
  } catch (err) {
    console.error('Retell create-phone-call error:', err);
    return null;
  }
}

// Datos post-llamada de Retell (lo que usamos para el post-análisis).
export type DetalleLlamada = {
  callId: string;
  leadId: string | null;
  toNumber: string | null;
  transcript: string | null;
  recordingUrl: string | null;
  callStatus: string | null;
  duracionSeg: number | null;
  analysis: unknown;
};

// Consulta autoritativa de una llamada por su id (el webhook solo nos da el call_id; releemos de
// Retell con nuestra API key para tener el dato real y autenticado).
export async function obtenerLlamada(callId: string): Promise<DetalleLlamada | null> {
  if (!env.RETELL_API_KEY) return null;
  try {
    const res = await fetch(`${GET_CALL_URL}/${encodeURIComponent(callId)}`, {
      headers: { Authorization: `Bearer ${env.RETELL_API_KEY}` },
    });
    if (!res.ok) {
      console.error(`Retell get-call ${res.status}: ${await res.text()}`);
      return null;
    }
    const c = (await res.json()) as Record<string, unknown>;
    const meta = (c.metadata ?? {}) as Record<string, unknown>;
    const start = typeof c.start_timestamp === 'number' ? c.start_timestamp : null;
    const end = typeof c.end_timestamp === 'number' ? c.end_timestamp : null;
    return {
      callId: String(c.call_id ?? callId),
      leadId: typeof meta.lead_id === 'string' ? meta.lead_id : null,
      toNumber: typeof c.to_number === 'string' ? c.to_number : null,
      transcript: typeof c.transcript === 'string' ? c.transcript : null,
      recordingUrl: typeof c.recording_url === 'string' ? c.recording_url : null,
      callStatus: typeof c.call_status === 'string' ? c.call_status : null,
      duracionSeg: start && end ? Math.round((end - start) / 1000) : null,
      analysis: c.call_analysis ?? null,
    };
  } catch (err) {
    console.error('Retell get-call error:', err);
    return null;
  }
}

// Descarga la grabación de Retell y la devuelve como data URI para almacenarla en nuestro sistema
// (control de retención propio, sin depender de la URL de Retell que puede caducar).
export async function descargarGrabacion(url: string): Promise<string | null> {
  try {
    const res = await fetch(url);
    if (!res.ok) return null;
    const tipo = res.headers.get('content-type') || 'audio/wav';
    const buf = Buffer.from(await res.arrayBuffer());
    return `data:${tipo};base64,${buf.toString('base64')}`;
  } catch (err) {
    console.error('descargarGrabacion error:', err);
    return null;
  }
}
