<?php

namespace App\Jobs;

use App\Models\PlatformConnection;
use App\Services\Platforms\Auth\TokenRefresherFactory;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Log;
use Throwable;

class RefreshPlatformTokensJob implements ShouldQueue
{
    use Queueable;

    public int $tries = 2;

    public int $timeout = 180;

    /**
     * Create a new job instance.
     *
     * @param  int|null  $connectionId  Optional single connection to refresh, or null to scan all expiring.
     * @param  int  $daysThreshold  Threshold in days before expiration to trigger refresh (default 10 days).
     */
    public function __construct(
        public ?int $connectionId = null,
        public int $daysThreshold = 10,
    ) {}

    /**
     * Execute the job.
     */
    public function handle(TokenRefresherFactory $factory): void
    {
        $connections = $this->connectionId !== null
            ? PlatformConnection::query()->whereKey($this->connectionId)->get()
            : PlatformConnection::query()
                ->active()
                ->where(function ($query): void {
                    $query->whereNotNull('refresh_token')
                        ->orWhere('platform', 'meta');
                })
                ->get()
                ->filter(fn (PlatformConnection $c): bool => $c->needsRefresh($this->daysThreshold));

        Log::info('Running platform token refresh job', [
            'count' => $connections->count(),
            'threshold_days' => $this->daysThreshold,
        ]);

        foreach ($connections as $connection) {
            try {
                $refresher = $factory->for($connection);
                $refresher->refresh($connection);

                Log::info("Successfully refreshed {$connection->platform} token", [
                    'connection_id' => $connection->id,
                    'platform' => $connection->platform,
                    'new_expires_at' => $connection->expires_at?->toIso8601String(),
                ]);
            } catch (Throwable $e) {
                Log::error("Failed to refresh {$connection->platform} token", [
                    'connection_id' => $connection->id,
                    'platform' => $connection->platform,
                    'error' => $e->getMessage(),
                ]);

                $connection->update([
                    'last_error' => $e->getMessage(),
                ]);
            }
        }
    }
}
