<?php

namespace App\Services\Communications\Drivers;

use App\Models\Communication\Call;
use Twilio\Rest\Client;

class TwilioVoiceDriver {
    protected string $apiKey;
    protected string $apiSecret;
    protected string $masterAccountSid;

    public function __construct() {
        $this->apiKey           = config('services.twilio.api_key');
        $this->apiSecret        = config('services.twilio.api_secret');
        $this->masterAccountSid = config('services.twilio.sid');
    }

    public function createOutboundCall(
        Call   $call,
        string $twimlUrl,
        string $statusCallbackUrl,
        string $recordingStatusCallbackUrl
    ): array {
        // Use the phone number's subaccount SID when available so each tenant's
        // calls are billed and logged under their own subaccount. Authentication
        // always uses the single master API key/secret pair.
        $accountSid = $call->phoneNumber?->twilio_subaccount_sid
            ?? $this->masterAccountSid;

        $response = $this->client($accountSid)->calls->create(
            $call->to_number,
            $call->from_number,
            [
                'url'    => $twimlUrl,
                'method' => 'POST',

                'statusCallback'       => $statusCallbackUrl,
                'statusCallbackMethod' => 'POST',
                'statusCallbackEvent'  => ['initiated', 'ringing', 'answered', 'completed'],

                'record'                          => (bool) $call->is_recorded,
                'recordingStatusCallback'         => $recordingStatusCallbackUrl,
                'recordingStatusCallbackMethod'   => 'POST',
                'recordingStatusCallbackEvent'    => ['completed'],
            ]
        );

        return [
            'sid'    => $response->sid    ?? null,
            'status' => $response->status ?? null,
            'to'     => $response->to     ?? null,
            'from'   => $response->from   ?? null,
            'raw'    => $response->toArray(),
        ];
    }

    /**
     * Download a recording audio file from Twilio.
     * Returns the raw audio bytes, or null on failure.
     */
    public function downloadRecording(string $recordingUrl, ?string $subaccountSid = null): ?string {
        // Ensure the URL ends with .mp3 so Twilio serves the audio file.
        $url = rtrim($recordingUrl, '/');
        if (!str_ends_with($url, '.mp3')) {
            $url .= '.mp3';
        }

        // Authenticate with the API key/secret pair, which works against both
        // the master account and any subaccount recordings.
        $response = \Illuminate\Support\Facades\Http::withBasicAuth($this->apiKey, $this->apiSecret)
            ->get($url);

        if (!$response->successful()) {
            return null;
        }

        return $response->body();
    }

    protected function client(string $accountSid): Client {
        // Authenticate with the single master API key/secret pair.
        // Passing $accountSid as the third argument scopes all API calls to
        // that account (subaccount or master) without needing separate secrets.
        return new Client($this->apiKey, $this->apiSecret, $accountSid);
    }
}
