<?php

namespace DefStudio\GameEngine\Database\Factories;

use Illuminate\Support\Str;
use DefStudio\GameEngine\Enums\Role;
use DefStudio\GameEngine\Models\Team;
use DefStudio\GameEngine\Models\User;
use DefStudio\GameEngine\Enums\Permission;
use DefStudio\GameEngine\Models\Organization;
use Illuminate\Database\Eloquent\Factories\Factory;
use DefStudio\GameEngine\Tests\Support\Models\Permission as PermissionModel;

class UserFactory extends Factory
{
    public function modelName(): string
    {
        return game_engine()->userClass();
    }

    public function definition(): array
    {
        return [
            'name' => fake()->name(),
            'email' => fake()->unique()->safeEmail(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'two_factor_secret' => null,
            'two_factor_recovery_codes' => null,
            'remember_token' => Str::random(10),
            'profile_photo_path' => null,
            'locale' => 'en',
        ];
    }

    public function role(Role $role = null): static
    {
        if ($role === null) {
            return $this;
        }

        return $this->afterCreating(fn(User $user) => $user->assignRole($role->value));
    }

    public function permission(Permission|string $permission = null): static
    {
        if ($permission === null) {
            return $this;
        }

        $permission_name = is_string($permission) ? $permission : $permission->value;

        return $this->afterCreating(fn(User $user) => $user->givePermissionTo(PermissionModel::findOrCreate($permission_name)));
    }

    public function unverified(): static
    {
        return $this->state(function(array $attributes) {
            return [
                'email_verified_at' => null,
            ];
        });
    }

    public function for_organization(Organization $organization, Role $role, bool $switch = false): UserFactory
    {
        return $this->afterCreating(function(User $user) use ($switch, $organization, $role) {
            $user->subscribe_to_organization($organization, $role, $switch);
        });
    }

    public function for_team(Team $team, Role $role = null, $switch = false): UserFactory
    {
        $factory = $role === null
            ? $this
            : $this->for_organization($team->organization, $role, $switch);

        return $factory->afterCreating(function(User $user) use ($team) {
            $user->subscribe_to_team($team);
        });
    }
}
