<?php

namespace App\Services;

use App\Repositories\Eloquent\RoleRepository;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use Illuminate\Database\Eloquent\Collection;

class RoleService
{
    protected RoleRepository $roleRepository;
    protected LoggingService $loggingService;

    public function __construct(RoleRepository $roleRepository, LoggingService $loggingService)
    {
        $this->roleRepository = $roleRepository;
        $this->loggingService = $loggingService;
    }

    public function getAllRoles(): Collection
    {
        $this->loggingService->logService('RoleService::getAllRoles');
        return $this->roleRepository->getAllWithPermissions();
    }

    public function getRole(int $id): Role
    {
        $this->loggingService->logService('RoleService::getRole', ['id' => $id]);
        return $this->roleRepository->with(['permissions'])->findOrFail($id);
    }

    public function createRole(array $data): Role
    {
        $this->loggingService->logService('RoleService::createRole', $data);

        $role = Role::create([
            'name' => $data['name'],
            'guard_name' => 'sanctum',
        ]);

        if (!empty($data['permissions'])) {
            $role->syncPermissions($data['permissions']);
        }

        $this->loggingService->logService('RoleService::createRole', null, "Role {$role->id} created");
        return $role->load('permissions');
    }

    public function updateRole(int $id, array $data): Role
    {
        $this->loggingService->logService('RoleService::updateRole', ['id' => $id, 'data' => $data]);

        $role = Role::findOrFail($id);

        if (isset($data['name'])) {
            $role->update(['name' => $data['name']]);
        }

        if (isset($data['permissions'])) {
            $role->syncPermissions($data['permissions']);
        }

        $this->loggingService->logService('RoleService::updateRole', null, "Role {$id} updated");
        return $role->fresh()->load('permissions');
    }

    public function deleteRole(int $id): bool
    {
        $this->loggingService->logService('RoleService::deleteRole', ['id' => $id]);

        $role = Role::findOrFail($id);

        if (in_array($role->name, ['super-admin', 'branch-admin'])) {
            throw new \Exception('Cannot delete system roles');
        }

        $result = $role->delete();
        $this->loggingService->logService('RoleService::deleteRole', null, "Role {$id} deleted");
        return $result;
    }

    public function syncPermissions(int $roleId, array $permissions): Role
    {
        $this->loggingService->logService('RoleService::syncPermissions', ['role_id' => $roleId, 'permissions' => $permissions]);

        $role = Role::findOrFail($roleId);
        $role->syncPermissions($permissions);

        $this->loggingService->logService('RoleService::syncPermissions', null, "Permissions synced for role {$roleId}");
        return $role->load('permissions');
    }

    public function getRolePermissions(int $roleId): Collection
    {
        $this->loggingService->logService('RoleService::getRolePermissions', ['role_id' => $roleId]);
        $role = Role::findOrFail($roleId);
        return $role->permissions;
    }
}
