<?php

namespace App\Services\Platforms\Auth;

use App\Contracts\PlatformTokenRefresher;
use App\Models\PlatformConnection;
use Illuminate\Support\Facades\Http;
use RuntimeException;

class MetaTokenRefresher implements PlatformTokenRefresher
{
    public function refresh(PlatformConnection $connection): PlatformConnection
    {
        $token = (string) $connection->access_token;

        if (blank($token)) {
            $error = 'Meta connection cannot be refreshed: access_token is missing.';
            $connection->update(['last_error' => $error]);

            throw new RuntimeException($error);
        }

        $appId = (string) ($connection->platform_data['app_id'] ?? config('services.meta.client_id') ?? env('META_APP_ID'));
        $appSecret = (string) ($connection->platform_data['app_secret'] ?? config('services.meta.client_secret') ?? env('META_APP_SECRET'));
        $version = (string) config('platforms.meta.version', 'v23.0');

        if (blank($appId) || blank($appSecret)) {
            // System user tokens on Meta do not expire or need refresh.
            // If app credentials are not configured, record last_refreshed_at and extend expiry.
            $connection->update([
                'last_refreshed_at' => now(),
                'expires_at' => now()->addDays(60),
                'last_error' => null,
            ]);

            return $connection->fresh();
        }

        $response = Http::connectTimeout(5)
            ->timeout(10)
            ->get("https://graph.facebook.com/{$version}/oauth/access_token", [
                'grant_type' => 'fb_exchange_token',
                'client_id' => $appId,
                'client_secret' => $appSecret,
                'fb_exchange_token' => $token,
            ]);

        if ($response->failed() || ! is_string($response->json('access_token'))) {
            $error = sprintf('Meta token refresh failed: %s', $response->body());
            $connection->update(['last_error' => $error]);

            throw new RuntimeException($error);
        }

        $expiresIn = (int) $response->json('expires_in', 5184000); // 60 days

        $connection->update([
            'access_token' => (string) $response->json('access_token'),
            'expires_at' => now()->addSeconds($expiresIn),
            'last_refreshed_at' => now(),
            'last_error' => null,
        ]);

        return $connection->fresh();
    }
}
