<?php

namespace App\Services;

use App\Models\Permission;
use App\Models\Role;
use App\Models\User;

class PermissionService
{
    public function createPermission($name, $displayName = null, $description = null)
    {
        $isWildcard = str_contains($name, '*');

        return Permission::create([
            'name' => $name,
            'display_name' => $displayName ?? $name,
            'description' => $description,
            'is_wildcard' => $isWildcard
        ]);
    }

    public function createRole($name, $displayName = null, $description = null)
    {
        return Role::create([
            'name' => $name,
            'display_name' => $displayName ?? $name,
            'description' => $description
        ]);
    }

    public function assignPermissionToRole($permission, $role)
    {
        if (is_string($permission)) {
            $permission = Permission::where('name', $permission)->firstOrFail();
        }

        if (is_string($role)) {
            $role = Role::where('name', $role)->firstOrFail();
        }

        $role->permissions()->syncWithoutDetaching([$permission->id]);

        return $role;
    }

    public function removePermissionFromRole($permission, $role)
    {
        if (is_string($permission)) {
            $permission = Permission::where('name', $permission)->firstOrFail();
        }

        if (is_string($role)) {
            $role = Role::where('name', $role)->firstOrFail();
        }

        $role->permissions()->detach($permission->id);

        return $role;
    }

    public function getUserPermissions(User $user)
    {
        // Get direct permissions
        $directPermissions = $user->permissions;

        // Get role-based permissions
        $rolePermissions = collect();
        foreach ($user->roles as $role) {
            $rolePermissions = $rolePermissions->merge($role->permissions);
        }

        // Merge and remove duplicates
        return $directPermissions->merge($rolePermissions)->unique('id');
    }

    public function checkPermission(User $user, $permission)
    {
        return $user->hasPermission($permission);
    }

    public function getMatchingPermissions($permissionPattern)
    {
        $allPermissions = Permission::all();
        $matchingPermissions = collect();

        foreach ($allPermissions as $perm) {
            if ($perm->is_wildcard && $perm->matches($permissionPattern)) {
                $matchingPermissions->push($perm);
            } elseif ($perm->name === $permissionPattern) {
                $matchingPermissions->push($perm);
            }
        }

        return $matchingPermissions;
    }

    public function syncRolePermissions(Role $role, array $permissions)
    {
        $permissionIds = [];

        foreach ($permissions as $permission) {
            if (is_string($permission)) {
                $perm = Permission::where('name', $permission)->first();
                if ($perm) {
                    $permissionIds[] = $perm->id;
                }
            } else {
                $permissionIds[] = $permission->id;
            }
        }

        $role->permissions()->sync($permissionIds);

        return $role;
    }
}
