<?php

declare(strict_types=1);

namespace apexl\Io\modules\user\services;

use apexl\Io\modules\user\collections\permissionCollection;
use apexl\Io\modules\user\collections\roleCollection;
use apexl\Io\modules\user\entities\roleEntity;
use apexl\Io\modules\user\entities\userEntity;
use apexl\Io\modules\user\enums\permissions\Common;
use apexl\Io\modules\user\interfaces\PermissionInterface;
use apexl\Vault\Vault;

final readonly class userPermissionManagerService
{
    public final const string TABLE__PERMISSIONS_USERS = 'permissions__users';
    private bool $isGodUser;

    public function __construct(
        private userEntity $user,
        private roleCollection $roles,
        private Vault $vault,
    ) {
        $this->isGodUser = $this->isGodUser();
    }

    private function isGodUser(): bool
    {
        return config('auth.enableGodUser') && $this->user->id == 1;
    }

    public function can(PermissionInterface $permission): bool
    {
        if ($this->isGodUser) {
            return true;
        }

        if ($this->permissions()->contains(Common::BYPASS)) {
            return true;
        }

        if ($this->permissions()->contains($permission)) {
            return true;
        }

        return false;
    }

    public function permissions(bool $includeRoles = true): permissionCollection
    {
        $userId = $this->user->id;

        $permissions = permissionCollection::createFromQueryResult(
            $this->vault->select(self::TABLE__PERMISSIONS_USERS)
                ->fields('permission')
                ->where('user', $userId)
                ->execute()
                ->fetchAll()
        );

        if ($includeRoles) {
            $this->roles->each(fn(roleEntity $role) => $permissions->merge(
                $role->permissions()
            ));
        }

        return $permissions->unique();
    }

    public function add(PermissionInterface $permission): void
    {
        $userId = $this->user->id;
        $this->vault->insert(self::TABLE__PERMISSIONS_USERS)
            ->fields([
                'user' => $userId,
                'permission' => serialize($permission),
            ])->execute();
    }

    public function remove(PermissionInterface $permission): void
    {
        $userId = $this->user->id;
        $this->vault->delete(self::TABLE__PERMISSIONS_USERS)
            ->where('user', $userId)
            ->where('permission', serialize($permission))
            ->execute();
    }


}
