<?php

namespace App\Services\AccessControl;

use App\Models\RolePermission;
use Illuminate\Support\Facades\Cache;

class PermissionRegistry
{
    public static function modules(): array
    {
        $modules = config('ngbvd_permissions.modules', []);
        $normalized = [];

        foreach ($modules as $module => $permissions) {
            $normalized[$module] = [];
            foreach ($permissions as $action => $definition) {
                if (is_int($action)) {
                    $action = $definition;
                    $definition = ['label' => ucwords(str_replace('_', ' ', $action)), 'description' => ''];
                } elseif (is_string($definition)) {
                    $definition = ['label' => $definition, 'description' => ''];
                } elseif (!is_array($definition)) {
                    $definition = ['label' => (string) $action, 'description' => ''];
                }
                $normalized[$module][$module.'.'.$action] = $definition;
            }
        }

        return $normalized;
    }

    public static function allPermissionKeys(): array
    {
        $keys = [];
        foreach (self::modules() as $permissions) {
            foreach ($permissions as $key => $definition) {
                $keys[] = $key;
            }
        }
        return $keys;
    }

    public function totalPermissions(): int
    {
        return count(self::allPermissionKeys());
    }

    public function forRole($roleId): array
    {
        if (!$roleId) {
            return [];
        }

        return Cache::remember('ngbvd_role_permissions_' . $roleId, 60, function () use ($roleId) {
            try {
                return RolePermission::where('role_id', $roleId)
                    ->where('is_allowed', 1)
                    ->get()
                    ->map(function ($row) { return $row->module . '.' . $row->permission; })
                    ->values()
                    ->all();
            } catch (\Throwable $e) {
                return [];
            }
        });
    }

    public function roleCoverage($roleId): array
    {
        $total = $this->totalPermissions();
        $assigned = count($this->forRole($roleId));
        $percentage = $total > 0 ? (int) round(($assigned / $total) * 100) : 0;

        return [
            'assigned' => $assigned,
            'total' => $total,
            'percentage' => $percentage,
        ];
    }

    public static function clearRoleCache($roleId): void
    {
        Cache::forget('ngbvd_role_permissions_' . $roleId);
    }
}
