/**
 * sip-transfer.service.ts — SIP-native call transfer via jambonz REST.
 *
 * Strict isolation: SIP calls MUST NOT route through Twilio's `transferCall`
 * (which uses Twilio REST + TwiML). For provider='sip' calls we update the
 * in-progress call on jambonz with a fresh app_json that dials the human
 * fallback number, then mark the session as escalated.
 *
 * See engine/voice-core.ts for the full SIP file map.
 */
import { db } from '@server/db/drizzle';
import { sql } from 'drizzle-orm';
import { ValidationError } from '@server/errors';
import { getJambonzCreds } from '@server/services/telephone/jambonz/jambonz.service';

interface SipSessionRow {
  id: string;
  sip_call_id: string | null;
  status: string;
  caller_number: string | null;
  callee_number: string | null;
}

export async function transferSipCall(
  sessionId: string,
  restaurantId: string,
  targetNumber: string
): Promise<void> {
  /* raw: SELECT id, sip_call_id, status, caller_number, callee_number FROM sip_call_sessions WHERE id = $1 AND restaurant_id = $2 */
  const { rows } = await db.execute(sql`
    SELECT id, sip_call_id, status, caller_number, callee_number
    FROM sip_call_sessions WHERE id = ${sessionId} AND restaurant_id = ${restaurantId}
  `);
  const session = rows[0] as unknown as SipSessionRow | undefined;
  if (!session) throw new ValidationError('Call session not found');
  if (session.status !== 'active') throw new ValidationError('Call is not active');
  if (!session.sip_call_id) throw new ValidationError('No jambonz call SID for this session');

  const creds = await getJambonzCreds(restaurantId);
  if (!creds) throw new ValidationError('jambonz is not configured for this restaurant');

  // Replace the in-progress call's app with a Dial verb that bridges the
  // caller to the human fallback number. The original caller-id is preserved
  // (`callerId`) so the human sees who is calling.
  const callerId = session.callee_number || session.caller_number || '';
  const appJson = [
    { verb: 'say', text: 'Please hold while we connect you.' },
    {
      verb: 'dial',
      callerId,
      answerOnBridge: true,
      target: [{ type: 'phone', number: targetNumber }],
    },
  ];

  const url = `${creds.baseUrl}/v1/Accounts/${creds.accountSid}/Calls/${session.sip_call_id}`;
  const res = await fetch(url, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${creds.apiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ call_hook: appJson }),
  });

  if (!res.ok) {
    const text = await res.text().catch(() => '');
    throw new ValidationError(`jambonz transfer failed: HTTP ${res.status} ${text}`);
  }

  /* raw: UPDATE sip_call_sessions SET escalated_to_human = true WHERE id = $1 */
  await db.execute(sql`UPDATE sip_call_sessions SET escalated_to_human = true WHERE id = ${sessionId}`);
}
