<?php
declare(strict_types=1);

namespace App\Modules\AccessMatrix\Services;

use App\Core\App;
use App\Core\Registries\PermissionRegistry;

final class PermissionDiscoveryService
{
    public static function findOrphanPermissions(): array
    {
        $registered = array_keys(PermissionRegistry::getAll());
        $usedInRoutes = self::getRoutePermissions();

        return array_values(array_diff($registered, $usedInRoutes));
    }

    public static function findUnprotectedRoutes(): array
    {
        $unprotected = [];
        $modulesPath = App::getInstance()->basePath() . '/app/Modules';

        $dirs = glob($modulesPath . '/*/Routes.php');
        foreach ($dirs as $routeFile) {
            $routes = require $routeFile;
            if (!is_array($routes)) {
                continue;
            }

            foreach ($routes as $route) {
                $permission = $route[4] ?? null;
                if (empty($permission)) {
                    $unprotected[] = [
                        'method'  => $route[0] ?? '?',
                        'path'    => $route[1] ?? '?',
                        'handler' => $route[2] ?? '?',
                        'file'    => basename(dirname($routeFile)),
                    ];
                }
            }
        }

        return $unprotected;
    }

    public static function getPermissionStats(): array
    {
        $grouped = PermissionRegistry::getAllGrouped();
        $stats = [];
        $total = 0;

        foreach ($grouped as $group => $perms) {
            $count = count($perms);
            $stats[$group] = $count;
            $total += $count;
        }

        arsort($stats);

        return [
            'total'      => $total,
            'groups'     => count($grouped),
            'by_group'   => $stats,
        ];
    }

    public static function getDependencies(): array
    {
        $db = App::getInstance()->db();

        try {
            $rows = $db->select("SELECT permission_key, requires_key, is_auto_grant FROM permission_dependencies ORDER BY permission_key");
        } catch (\Throwable $e) {
            return [];
        }

        $deps = [];
        foreach ($rows as $row) {
            $deps[$row['permission_key']][] = [
                'requires'    => $row['requires_key'],
                'auto_grant'  => (bool) $row['is_auto_grant'],
            ];
        }

        return $deps;
    }

    public static function validateRoleDependencies(int $roleId): array
    {
        $db = App::getInstance()->db();
        $violations = [];

        $rolePerms = array_column(
            $db->select("SELECT permission_key FROM role_permissions WHERE role_id = ?", [$roleId]),
            'permission_key'
        );

        if (in_array('*', $rolePerms, true)) {
            return [];
        }

        $deps = self::getDependencies();

        foreach ($rolePerms as $perm) {
            if (!isset($deps[$perm])) {
                continue;
            }

            foreach ($deps[$perm] as $dep) {
                if (!in_array($dep['requires'], $rolePerms, true)) {
                    $violations[] = [
                        'permission' => $perm,
                        'missing'    => $dep['requires'],
                    ];
                }
            }
        }

        return $violations;
    }

    private static function getRoutePermissions(): array
    {
        $permissions = [];
        $modulesPath = App::getInstance()->basePath() . '/app/Modules';

        $dirs = glob($modulesPath . '/*/Routes.php');
        foreach ($dirs as $routeFile) {
            $routes = require $routeFile;
            if (!is_array($routes)) {
                continue;
            }

            foreach ($routes as $route) {
                $permission = $route[4] ?? null;
                if ($permission) {
                    $permissions[] = $permission;
                }
            }
        }

        return array_unique($permissions);
    }
}
