<?php

namespace App\Services;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class FCMService
{
    /**
     * Generate OAuth2 Access Token for Firebase Messaging.
     * Caches the token for 50 minutes to avoid overhead.
     *
     * @return string|null
     */
    public static function getAccessToken()
    {
        return Cache::remember('fcm_access_token', 3000, function () {
            try {
                $credentialsPath = base_path('migrant-fe5a7-firebase-adminsdk-fbsvc-f8b365ecd0.json');
                
                if (!file_exists($credentialsPath)) {
                    Log::error("FCM Service Account JSON not found at: {$credentialsPath}");
                    return null;
                }

                $credentials = json_decode(file_get_contents($credentialsPath), true);
                if (!$credentials) {
                    Log::error("FCM Service Account JSON is invalid or empty.");
                    return null;
                }

                $privateKey = $credentials['private_key'];
                $clientEmail = $credentials['client_email'];

                $header = json_encode(['alg' => 'RS256', 'typ' => 'JWT']);
                
                $now = time();
                $payload = json_encode([
                    'iss' => $clientEmail,
                    'scope' => 'https://www.googleapis.com/auth/firebase.messaging',
                    'aud' => 'https://oauth2.googleapis.com/token',
                    'exp' => $now + 3600,
                    'iat' => $now,
                ]);

                $base64UrlHeader = self::base64UrlEncode($header);
                $base64UrlPayload = self::base64UrlEncode($payload);

                $signatureInput = $base64UrlHeader . '.' . $base64UrlPayload;
                $signature = '';

                if (!openssl_sign($signatureInput, $signature, $privateKey, OPENSSL_ALGO_SHA256)) {
                    Log::error("Failed to sign JWT with private key using openssl_sign.");
                    return null;
                }

                $base64UrlSignature = self::base64UrlEncode($signature);
                $jwtToken = $signatureInput . '.' . $base64UrlSignature;

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

                if ($response->failed()) {
                    Log::error("FCM OAuth2 request failed: " . $response->body());
                    return null;
                }

                $data = $response->json();
                return $data['access_token'] ?? null;

            } catch (\Exception $e) {
                Log::error("FCM Access Token Generation Error: " . $e->getMessage());
                return null;
            }
        });
    }

    /**
     * Send a Push Notification to a specific FCM token.
     *
     * @param string $token
     * @param string $title
     * @param string $body
     * @param array $data
     * @return bool
     */
    public static function sendPushNotification($token, $title, $body, array $data = [])
    {
        if (empty($token)) {
            return false;
        }

        try {
            $accessToken = self::getAccessToken();
            if (!$accessToken) {
                Log::error("Cannot send push notification: FCM Access Token is null.");
                return false;
            }

            // Load credentials to fetch the correct project_id
            $credentialsPath = base_path('migrant-fe5a7-firebase-adminsdk-fbsvc-f8b365ecd0.json');
            $credentials = json_decode(file_get_contents($credentialsPath), true);
            $projectId = $credentials['project_id'] ?? 'migrant-fe5a7';

            // Convert all data array values to strings as required by FCM v1
            $formattedData = [];
            foreach ($data as $key => $value) {
                $formattedData[(string)$key] = (string)$value;
            }

            $payload = [
                'message' => [
                    'token' => $token,
                    'notification' => [
                        'title' => $title,
                        'body' => $body,
                    ],
                ]
            ];

            if (!empty($formattedData)) {
                $payload['message']['data'] = $formattedData;
            }

            $response = Http::withToken($accessToken)
                ->post("https://fcm.googleapis.com/v1/projects/{$projectId}/messages:send", $payload);

            if ($response->failed()) {
                Log::error("FCM Push Notification failed: " . $response->body());
                return false;
            }

            return true;

        } catch (\Exception $e) {
            Log::error("FCM Notification Dispatch Failure: " . $e->getMessage());
            return false;
        }
    }

    /**
     * Base64 Url Encode helper.
     *
     * @param string $data
     * @return string
     */
    private static function base64UrlEncode($data)
    {
        return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($data));
    }
}
