<?php

namespace App\Console\Commands;

use App\Models\User;
use Illuminate\Console\Command;
use Spatie\Permission\Models\Role;

use function Laravel\Prompts\error;
use function Laravel\Prompts\info;
use function Laravel\Prompts\search;
use function Laravel\Prompts\select;
use function Laravel\Prompts\table;

class AssignUserRole extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'user:assign-role 
                            {--user= : The user ID or email}
                            {--role= : The role name to assign}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Assign a role to a user';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        // Get or select user
        $userIdentifier = $this->option('user');

        if (! $userIdentifier) {
            $userIdentifier = search(
                label: 'Search for a user by name or email:',
                placeholder: 'Start typing...',
                options: fn (string $value) => strlen($value) > 0
                    ? User::where('name', 'like', "%{$value}%")
                        ->orWhere('email', 'like', "%{$value}%")
                        ->limit(10)
                        ->get()
                        ->mapWithKeys(fn ($user) => [$user->id => "{$user->name} ({$user->email})"])
                        ->all()
                    : [],
            );
        }

        $user = is_numeric($userIdentifier)
            ? User::find($userIdentifier)
            : User::where('email', $userIdentifier)->first();

        if (! $user) {
            error("User not found: {$userIdentifier}");

            return self::FAILURE;
        }

        // Get or select role
        $roleName = $this->option('role');

        if (! $roleName) {
            $roles = Role::pluck('name')->toArray();
            $roleName = select(
                label: 'Select a role to assign:',
                options: $roles,
            );
        }

        $role = Role::where('name', $roleName)->first();

        if (! $role) {
            error("Role not found: {$roleName}");

            return self::FAILURE;
        }

        // Assign role
        $user->syncRoles([$role]);

        info("Role '{$roleName}' assigned to user '{$user->name}' ({$user->email})");

        // Show current roles and permissions
        table(
            headers: ['Property', 'Value'],
            rows: [
                ['User', $user->name],
                ['Email', $user->email],
                ['Roles', $user->getRoleNames()->implode(', ')],
                ['Permissions Count', $user->getAllPermissions()->count()],
            ]
        );

        return self::SUCCESS;
    }
}
