<?php declare(strict_types=1);

namespace App\Services\Role;

use App\Enums\Permission;
use App\Exceptions\Rule\RoleSyncPermissionsCommandHandlerException;
use App\Models\Role;
use App\Models\RolePermission;

final readonly class RoleSyncPermissionsCommandHandler
{
    public function handle(Role $role, array $dataPermissions): Role
    {
        $rolePermissions = $role->permissions->pluck('id', 'permission')->toArray();

        $data = $this->getInsertDeleteData($role->id, $rolePermissions, $dataPermissions);

        if (!empty($data['insert'])) {
            RolePermission::query()->insert($data['insert']);
        }

        if (!empty($data['delete'])) {
            RolePermission::query()->whereIn('id', $data['delete'])->delete();
        }

        return $role;
    }

    private function getInsertDeleteData(int $roleId, array $rolePermissions, array $permissionsData): array
    {
        $data = [
            'insert' => [],
            'delete' => []
        ];

        $permissions = Permission::toArrayListCodes();
        foreach ($permissionsData as $permission) {
            if (array_search($permission, $permissions) === false) {
                throw new RoleSyncPermissionsCommandHandlerException('Таких разрешений в системе нет: ' . $permission);
            }

            if (isset($rolePermissions[$permission])) {
                unset($rolePermissions[$permission]);
                continue;
            }

            $data['insert'][] = [
                'role_id' => $roleId,
                'permission' => $permission,
            ];
        }

        $data['delete'] = array_values($rolePermissions);

        return $data;
    }
}