<?php

namespace App\Services;

use Illuminate\Validation\ValidationException;
use Spatie\Permission\Models\Role;

class RoleService
{
    /**
     * Roles that ship with the system and cannot be deleted.
     */
    private const SYSTEM_ROLES = [
        'super-admin',
        'kyc-manager',
        'kyc-reviewer',
        'external',
        'analytics-viewer',
        'auditor',
    ];

    public function isSystemRole(string $name): bool
    {
        return in_array($name, self::SYSTEM_ROLES, strict: true);
    }

    /**
     * Create a custom role and optionally assign permissions to it.
     */
    public function create(array $data): Role
    {
        $role = Role::create(['name' => $data['name'], 'guard_name' => 'web']);

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

        return $role;
    }

    /**
     * Rename a role. System roles cannot be renamed.
     */
    public function update(Role $role, array $data): Role
    {
        if ($this->isSystemRole($role->name)) {
            throw ValidationException::withMessages(['role' => 'System roles cannot be renamed.']);
        }

        $role->name = $data['name'];
        $role->save();

        return $role;
    }

    /**
     * Delete a role. System roles cannot be deleted.
     * Users with only this role will have no role after deletion.
     */
    public function delete(Role $role): void
    {
        if ($this->isSystemRole($role->name)) {
            throw ValidationException::withMessages(['role' => 'System roles cannot be deleted.']);
        }

        $role->delete();
    }

    /**
     * Sync permissions on a role — replaces all existing permissions.
     * super-admin permissions cannot be modified (gate bypass handles access).
     */
    public function syncPermissions(Role $role, array $permissions): Role
    {
        if ($role->name === 'super-admin') {
            throw ValidationException::withMessages(['role' => 'The super-admin role permissions cannot be modified.']);
        }

        $role->syncPermissions($permissions);

        return $role;
    }
}
