<?php
/**
 * Permission Tree
 *
 * Handles hierarchical tree generation for permissions.
 *
 * @package FleekDash\Core
 * @since 2.3.0
 */

namespace FleekDash\Core;

defined('ABSPATH') || exit;

class PermissionTree {
    /**
     * Get permission tree for Role Editor UI
     *
     * @param string|null $root_id Root permission ID
     * @return array Permission tree
     */
    public static function getTree(?string $root_id = null): array {
        $registry = PermissionRegistry::getAll();

        if ($root_id) {
            $root = $registry[$root_id] ?? null;
            if (!$root) {
                return [];
            }
            return [$root, ...self::getDescendants($root_id)];
        }

        // Get all root permissions (no parent)
        $roots = array_filter($registry, function($node) {
            return empty($node['parent']);
        });

        return array_map([self::class, 'buildTreeNode'], $roots);
    }

    /**
     * Build tree node with children
     *
     * @param array $node Permission node
     * @return array Tree node with children
     */
    private static function buildTreeNode(array $node): array {
        $registry = PermissionRegistry::getAll();
        $children = array_filter($registry, function($p) use ($node) {
            return ($p['parent'] ?? '') === $node['id'];
        });

        $children = array_map([self::class, 'buildTreeNode'], array_values($children));

        return array_merge($node, [
            'children' => !empty($children) ? $children : null,
        ]);
    }

    /**
     * Get descendants of a permission
     * @param string $permission_id Permission ID
     * @return array Descendants
     */
    public static function getDescendants(string $permission_id): array {
        $registry = PermissionRegistry::getAll();
        $descendants = [];
        $to_process = [$permission_id];

        while (!empty($to_process)) {
            $current_id = array_shift($to_process);
            $children = array_filter($registry, function($p) use ($current_id) {
                return ($p['parent'] ?? '') === $current_id;
            });

            $descendants = array_merge($descendants, array_values($children));
            $to_process = array_merge($to_process, array_column($children, 'id'));
        }

        return $descendants;
    }
}
