<?php

namespace DefStudio\GameEngine\Actions\Users;

use Illuminate\Support\Str;
use DefStudio\Actions\Action;
use DefStudio\GameEngine\Enums\Role;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Hash;
use DefStudio\GameEngine\Models\User;
use DefStudio\GameEngine\Events\Users\UserSaved;
use DefStudio\GameEngine\Events\Users\UserCreated;
use DefStudio\GameEngine\Events\Users\UserUpdated;

/**
 * @method static User run(User $user, iterable $roles = [])
 */
class SaveUser extends Action
{
    public function handle(User $user): User
    {
        $this->authorize($user);

        if (!$user->exists) {
            $password = Str::password();
            $user->password = Hash::make($password);
            $user->save();

            UserCreated::dispatch($user, $password);
        } else {
            $user->save();

            UserUpdated::dispatch($user);
        }

        UserSaved::dispatch($user);

        return $user;
    }

    public function authorize(User $user, iterable $roles = []): void
    {
        if ($user->exists) {
            Gate::authorize('update', $user);
        } else {
            $roles = collect($roles)->map(fn(string $role) => Role::from($role));
            if ($roles->isEmpty()) {
                Gate::authorize('create', game_engine()->userClass());
            } else {
                $roles->each(fn(Role $role) => Gate::authorize('create', $role));
            }
        }
    }
}
