<?php

namespace App\Console\Commands;

use App\Enums\UserRole;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Http;
use Illuminate\Contracts\Encryption\DecryptException;

class SyncSubscriptionKeys extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'app:sync-subscription-keys';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Sync local users against active subscription keys';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $endpoint = config('services.subscription_service_host');
        if (!$endpoint) {
            $this->error('Missing endpoint.');
            return self::FAILURE;
        }

        $response = Http::asJson()
            ->acceptJson()
            ->timeout(20)
            ->retry(3, 1000)
            ->post($endpoint.'/api/membership/keys', [
                'payload' => base64_encode(Crypt::encryptString('get-active-keys')),
            ]);

        if (! $response->successful()) {
            $this->error('Subscription API request failed: HTTP ' . $response->status());
            return self::FAILURE;
        }

        try {
            $decrypted = Crypt::decryptString(base64_decode($response->json('payload')));
            $activeKeys = json_decode($decrypted, true, flags: JSON_THROW_ON_ERROR);
        } catch (DecryptException $e) {
            $this->error('Could not decrypt API response.');
            return self::FAILURE;
        } catch (\JsonException $e) {
            $this->error('API returned invalid JSON.');
            return self::FAILURE;
        }

        if (! is_array($activeKeys)) {
            $this->error('API response payload was not an array.');
            return self::FAILURE;
        }

        $activeKeys = collect($activeKeys)
            ->filter(fn ($key) => is_string($key) && $key !== '')
            ->values()
            ->all();

        $this->markInactiveUsers($activeKeys);
        $this->markActiveUsers($activeKeys);

        return self::SUCCESS;
    }

    private function markInactiveUsers(array $activeKeys) 
    {
        User::query()
            ->whereNotNull('subscription_key')
            ->whereNotIn('subscription_key', $activeKeys)
            ->chunk(100, function ($users) {
                foreach($users as $user) {
                    $user->removeRole(UserRole::SUPPORTER);
                }
            });
    }

    private function markActiveUsers(array $activeKeys)
    {
        User::query()
            ->whereNotNull('subscription_key')
            ->whereIn('subscription_key', $activeKeys)
            ->chunk(100, function ($users) {
                foreach($users as $user) {
                    $user->addRole(UserRole::SUPPORTER);
                }
            });
    }
}
