<?php

namespace App\Services;

use App\Models\User;
use Illuminate\Support\Facades\Http;

class FcmService
{
    private string $credentialsPath;

    public function __construct()
    {
        $this->credentialsPath = storage_path('app/firebase-credentials.json');
    }

    /**
     * Send a push notification to a single user.
     * Silently does nothing if user has no FCM token or credentials are missing.
     */
    public function sendToUser(User $user, string $title, string $body, array $data = []): void
    {
        if (! $user->fcm_token) return;
        if (! file_exists($this->credentialsPath)) return;

        try {
            $credentials = json_decode(file_get_contents($this->credentialsPath), true);
            $accessToken = $this->getAccessToken($credentials);

            Http::withToken($accessToken)
                ->post("https://fcm.googleapis.com/v1/projects/{$credentials['project_id']}/messages:send", [
                    'message' => [
                        'token'        => $user->fcm_token,
                        'notification' => ['title' => $title, 'body' => $body],
                        'data'         => array_map('strval', $data),
                        'android'      => ['priority' => 'high'],
                    ],
                ]);
        } catch (\Throwable $e) {
            logger()->error('FCM send failed: ' . $e->getMessage());
        }
    }

    /**
     * Exchange service account credentials for a short-lived OAuth2 access token.
     */
    private function getAccessToken(array $credentials): string
    {
        $now    = time();
        $header  = $this->base64UrlEncode(json_encode(['alg' => 'RS256', 'typ' => 'JWT']));
        $payload = $this->base64UrlEncode(json_encode([
            'iss'   => $credentials['client_email'],
            'scope' => 'https://www.googleapis.com/auth/firebase.messaging',
            'aud'   => 'https://oauth2.googleapis.com/token',
            'iat'   => $now,
            'exp'   => $now + 3600,
        ]));

        $signingInput = $header . '.' . $payload;
        openssl_sign($signingInput, $signature, $credentials['private_key'], 'SHA256');

        $jwt = $signingInput . '.' . $this->base64UrlEncode($signature);

        $response = Http::asForm()->post('https://oauth2.googleapis.com/token', [
            'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
            'assertion'  => $jwt,
        ]);

        return $response->json('access_token');
    }

    private function base64UrlEncode(string $data): string
    {
        return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
    }
}
