<?php

declare(strict_types=1);

namespace App\Framework\Console\Security;

final readonly class ConsoleUser
{
    /**
     * @param string $id
     * @param string $name
     * @param Permission[] $permissions
     * @param string[] $roles
     */
    public function __construct(
        public string $id,
        public string $name,
        public array $permissions = [],
        public array $roles = []
    ) {
    }

    public function hasPermission(Permission $permission): bool
    {
        return in_array($permission, $this->permissions, true);
    }

    public function hasAnyPermission(array $permissions): bool
    {
        foreach ($permissions as $permission) {
            if ($this->hasPermission($permission)) {
                return true;
            }
        }

        return false;
    }

    public function hasAllPermissions(array $permissions): bool
    {
        foreach ($permissions as $permission) {
            if (! $this->hasPermission($permission)) {
                return false;
            }
        }

        return true;
    }

    public function hasRole(string $role): bool
    {
        return in_array($role, $this->roles, true);
    }

    public function isAdmin(): bool
    {
        return $this->hasPermission(Permission::ADMIN) ||
               $this->hasPermission(Permission::SYSTEM_ADMIN);
    }

    public function getPermissionsByCategory(PermissionCategory $category): array
    {
        return array_filter(
            $this->permissions,
            fn (Permission $permission) => $permission->getCategory() === $category
        );
    }

    public static function anonymous(): self
    {
        return new self(
            id: 'anonymous',
            name: 'Anonymous User',
            permissions: [Permission::READ, Permission::EXECUTE],
            roles: ['guest']
        );
    }

    public static function admin(string $id = 'admin', string $name = 'Administrator'): self
    {
        return new self(
            id: $id,
            name: $name,
            permissions: Permission::cases(), // All permissions
            roles: ['admin', 'user']
        );
    }

    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'permissions' => array_map(fn (Permission $p) => $p->value, $this->permissions),
            'roles' => $this->roles,
            'is_admin' => $this->isAdmin(),
        ];
    }
}
