<?php

use App\Models\ApiToken;
use App\Models\User;
use Illuminate\Foundation\Console\ClosureCommand;
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;

Artisan::command('inspire', function () {
    /** @var ClosureCommand $this */
    $this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');

Artisan::command('api-token:issue {user : ID o email del usuario} {name=Integracion}', function () {
    /** @var ClosureCommand $this */
    $userArg = trim((string) $this->argument('user'));
    $name = trim((string) $this->argument('name'));

    $user = ctype_digit($userArg)
        ? User::query()->find((int) $userArg)
        : User::query()->where('email', $userArg)->first();

    if (! $user) {
        $this->error('Usuario no encontrado.');

        return self::FAILURE;
    }

    if ((int) ($user->organization_id ?? 0) <= 0) {
        $this->error('El usuario no tiene organización asignada.');

        return self::FAILURE;
    }

    [$token, $plainTextToken] = ApiToken::issueForUser($user, $name);

    $this->info('Token creado correctamente.');
    $this->line('token_id: '.$token->id);
    $this->line('user: '.$user->email);
    $this->line('name: '.$token->name);
    $this->line('secret: '.$plainTextToken);
    $this->warn('Guárdalo ahora. El secreto no se vuelve a mostrar.');

    return self::SUCCESS;
})->purpose('Genera un token API personal para un usuario owner/client.');

Artisan::command('api-token:list {user : ID o email del usuario}', function () {
    /** @var ClosureCommand $this */
    $userArg = trim((string) $this->argument('user'));

    $user = ctype_digit($userArg)
        ? User::query()->find((int) $userArg)
        : User::query()->where('email', $userArg)->first();

    if (! $user) {
        $this->error('Usuario no encontrado.');

        return self::FAILURE;
    }

    $rows = $user->apiTokens()
        ->orderByDesc('id')
        ->get(['id', 'name', 'token_prefix', 'last_used_at', 'revoked_at', 'created_at'])
        ->map(fn (ApiToken $token) => [
            'id' => $token->id,
            'name' => $token->name,
            'prefix' => $token->token_prefix,
            'last_used_at' => optional($token->last_used_at)->toDateTimeString(),
            'revoked_at' => optional($token->revoked_at)->toDateTimeString(),
            'created_at' => optional($token->created_at)->toDateTimeString(),
        ])
        ->all();

    $this->table(['ID', 'Nombre', 'Prefijo', 'Último uso', 'Revocado', 'Creado'], $rows);

    return self::SUCCESS;
})->purpose('Lista los tokens API de un usuario.');

Artisan::command('api-token:revoke {tokenId : ID del token}', function () {
    /** @var ClosureCommand $this */
    $token = ApiToken::query()->find((int) $this->argument('tokenId'));

    if (! $token) {
        $this->error('Token no encontrado.');

        return self::FAILURE;
    }

    $token->forceFill(['revoked_at' => now()])->save();
    $this->info('Token revocado.');

    return self::SUCCESS;
})->purpose('Revoca un token API.');
