<?php

namespace App\Http\Controllers\Twilio;

use App\Models\User\User;
use App\Services\Communications\TwilioClientIdentity;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Twilio\TwiML\VoiceResponse;

class TwilioTransferTwimlController {
    public function __invoke(Request $request): Response {
        $voice = new VoiceResponse();
        try {
            $toAgentId   = (int) $request->input('to_agent_id');
            $fromAgentId = (int) $request->input('from_agent_id');
            $toAgent     = User::find($toAgentId);

            $fallbackUrl = route('twilio.voice.transfer.fallback') . '?' . http_build_query([
                'from_agent_id' => $fromAgentId,
            ]);

            if (! $toAgent) {
                $voice->redirect($fallbackUrl . '&DialCallStatus=failed');
                return response((string) $voice, 200)->header('Content-Type', 'text/xml');
            }

            // Mirror the inbound <Dial> so transferred calls are recorded and
            // logged like any other answered call. Without `record` +
            // `recordingStatusCallback` Twilio captures nothing for the new
            // leg, and without the per-leg `statusCallback` `answered_at`
            // never gets set and the recording is misfiled as a voicemail.
            $dial = $voice->dial('', [
                'timeout'                       => 20,
                'action'                        => $fallbackUrl,
                'method'                        => 'POST',
                'record'                        => 'record-from-answer-dual',
                'recordingStatusCallback'       => route('twilio.voice.recording'),
                'recordingStatusCallbackMethod' => 'POST',
                'recordingStatusCallbackEvent'  => 'completed',
            ]);

            $dial->client(TwilioClientIdentity::for($toAgentId), [
                'statusCallbackEvent'  => 'answered',
                'statusCallback'       => route('twilio.voice.status'),
                'statusCallbackMethod' => 'POST',
            ]);

            return response((string) $voice, 200)->header('Content-Type', 'text/xml');

        } catch (\Throwable $exception) {
            logger()->error('TwilioTransferTwimlController error', [
                'message'      => $exception->getMessage(),
                'to_agent_id'  => $request->input('to_agent_id'),
                'from_agent_id'=> $request->input('from_agent_id'),
            ]);

            // Return valid TwiML so Twilio does not play "An application error has occurred".
            $voice->say('We were unable to complete the transfer. Please try again.');
            return response((string) $voice, 200)->header('Content-Type', 'text/xml');
        }
    }
}
