<?php

namespace App\Http\Middleware;

use App\Services\UserTypePermissionService;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class CheckPermission
{
    public function __construct(
        protected UserTypePermissionService $userTypePermissionService,
    ) {}

    /**
     * Handle an incoming request.
     *
     * @param  string  $scopes  A string of scopes separated by '|' to check a single permission against.
     * @param  string  $permissionType  The type of permission to check for each scope.
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function handle(Request $request, Closure $next, string $scopes, string $permissionType)
    {
        $user = Auth::user();

        $userPermissions = [];

        $userPermissions = $user
            ? $this->userTypePermissionService->allPermissionsByUserType($user->type)
            : $this->userTypePermissionService->allGuestPermissions();

        $hasPermission = false;

        foreach (explode(separator: '|', string: $scopes) as $scope) {
            if ($this->hasPermission(userPermissions: $userPermissions, scope: $scope, permissionType: $permissionType)) {
                $hasPermission = true;

                break;
            }
        }

        if (! $hasPermission) {
            return response()->json(data: ['message' => __('auth.unauthorized')], status: 403);
        }

        return $next($request);
    }

    private function hasPermission($userPermissions, string $scope, string $permissionType): bool
    {
        $bitwisePermissionTable = [
            'view'   => 1,
            'add'    => 2,
            'edit'   => 4,
            'delete' => 8,
            'print'  => 16,
            'export' => 32,
            'import' => 64,
            'limit'  => 128,
            'menu'   => 256,
        ];

        $requiredPermission = data_get($bitwisePermissionTable, $permissionType, 0);

        $permissionRecord = $userPermissions->first(function ($permission) use ($scope) {
            return $permission->permission->scope === $scope;
        });

        if (! $permissionRecord) {
            return false;
        }

        return ($permissionRecord->bits & $requiredPermission) === $requiredPermission;
    }
}
