
<?php

namespace App\Jobs;

use App\Helpers\CommonHelper;
use App\Model\Chatroom;
use App\Model\DeviceToken;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;

class SendVoIPPush implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $tries = 2;
    private $roomNumber;

    public function __construct($roomNumber)
    {
        $this->roomNumber = (int) $roomNumber;
    }

    public function handle()
    {
        $chatroom = Chatroom::with('patient')->where('id', $this->roomNumber)
            ->first();

        if (!$chatroom) {
            Log::warning('VoIP: Chatroom not found', ['room' => $this->roomNumber]);
            return;
        }

        $user = $chatroom->patient;
        $callerName = $user->first_name. " " . $user->last_name;
        $device = DeviceToken::where('user_id', $user->user_id)->first();

        if ($device) {
            if ($device->device_type === 'ios') {
                $this->sendToAPNs($device->token, $callerName, $user->user_id, env('APN_SANDBOX_MODE'));
            } else {
                $this->sendToFCM($user->user_id, $callerName, $user->user_id);
            }
        }
    }

    private function apnsJwt(): string
    {
        $teamId = config('services.apple.team_id');
        $keyId  = config('services.apple.key_id');
        $p8Path = config('services.apple.credentials_path');

        Log::info(
            'APNs config | ' .
            'team_id=' . var_export($teamId, true) . ' | ' .
            'key_id=' . var_export($keyId, true) . ' | ' .
            'p8_path=' . var_export($p8Path, true) . ' | ' .
            'exists=' . ($p8Path && file_exists($p8Path) ? 'YES' : 'NO')
        );

        if (!$p8Path || !file_exists($p8Path)) {
            throw new \RuntimeException("APNs .p8 file not found: {$p8Path}");
        }

        $header = ['alg' => 'ES256', 'kid' => $keyId];
        $claims = ['iss' => $teamId, 'iat' => time()];

        $b64 = function ($data) {
            return rtrim(strtr(base64_encode(json_encode($data)), '+/', '-_'), '=');
        };

        $unsignedJwt = $b64($header) . '.' . $b64($claims);

        $privateKey = file_get_contents($p8Path);
        openssl_sign($unsignedJwt, $signature, $privateKey, OPENSSL_ALGO_SHA256);

        return $unsignedJwt . '.' . rtrim(strtr(base64_encode($signature), '+/', '-_'), '=');
    }

    private function sendToAPNs($deviceToken, $callerName, $callerId, $sandbox = true)
    {
        try {
            $jwt = $this->apnsJwt();
            $bundleId = config('services.apple.bundle_id');

            $url = ($sandbox
                    ? 'https://api.sandbox.push.apple.com'
                    : 'https://api.push.apple.com'
                ) . "/3/device/{$deviceToken}";

            $headers = [
                "authorization: bearer {$jwt}",
                "apns-topic: {$bundleId}",
                "apns-push-type: voip",
                "apns-priority: 10",
                "apns-expiration: 0",
            ];

            $ch = curl_init($url);
            curl_setopt_array($ch, [
                CURLOPT_POST            => true,
                CURLOPT_HTTP_VERSION    => CURL_HTTP_VERSION_2_0,
                CURLOPT_HTTPHEADER      => $headers,
                CURLOPT_POSTFIELDS      => json_encode([
                    'aps' => [
                        'content-available' => 1,
                    ],
                    'type' => 'meeting.started',
                    'caller_name' => $callerName,
                    'caller_id' => $callerId,
                    'room_id' => $this->roomNumber,
                    'video' => true,
                ]),
                CURLOPT_RETURNTRANSFER  => true,
                CURLOPT_TIMEOUT         => 10,
            ]);

            $response = curl_exec($ch);
            $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);

            Log::info('APN for VoIP', ['status' => $status, 'response' => $response]);
        } catch (\Exception $e) {
            Log::error('VoIP APN failed', ['error' => $e->getMessage()]);
        }
    }

    private function sendToFCM($user_id, $callerName, $callerId)
    {
        try {
            $result = CommonHelper::sendPushNotifications(
                $user_id,
                'Incoming Video Call',
                'The therapist has joined the room already.', false,
                [
                    'type' => 'meeting.started',
                    'caller_name' => $callerName,
                    'caller_id' => $callerId,
                    'room_id' => $this->roomNumber
                ],
                'meeting.started',
            true
            );
            Log::info('FCM for VoIP', ['info' => $result]);
        } catch (\Exception $e) {
            Log::error('VoIP FCM failed', ['error' => $e->getMessage()]);
        }
    }
}
