<?php

declare(strict_types=1);

namespace App\Shared\Infrastructure\ApiPlatform\State;

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Shared\Infrastructure\ApiPlatform\Resource\SidebarResource;
use Symfony\Bundle\SecurityBundle\Security;

/**
 * @implements ProviderInterface<object>
 */
class SidebarProvider implements ProviderInterface
{
    /** @var list<string> */
    private readonly array $activeModuleIds;

    /** @var list<array{label: string, icon: string, permission?: string, items: list<array{label: string, to: string, icon: string, module: string, permission?: string}>}> */
    private readonly array $sidebarConfig;

    public function __construct(private readonly Security $security)
    {
        $configDir = dirname(__DIR__, 5).'/config';

        // Load active modules
        $modulesFile   = $configDir.'/modules.php';
        $moduleClasses = file_exists($modulesFile) ? require $modulesFile : [];

        $ids = [];
        foreach ($moduleClasses as $moduleClass) {
            if (defined($moduleClass.'::ID')) {
                $ids[] = $moduleClass::ID;
            }
        }
        $this->activeModuleIds = $ids;

        // Load sidebar config
        $sidebarFile         = $configDir.'/sidebar.php';
        $this->sidebarConfig = file_exists($sidebarFile) ? require $sidebarFile : [];
    }

    public function provide(Operation $operation, array $uriVariables = [], array $context = []): object
    {
        $sections       = [];
        $disabledRoutes = [];

        foreach ($this->sidebarConfig as $section) {
            // Gate de section (optionnel) : si la section declare une permission
            // et que l'utilisateur ne la possede pas, la section entiere est
            // masquee. Toutes les routes de ses items basculent dans
            // `disabledRoutes` pour que le middleware front redirige toute
            // navigation directe, y compris si l'item n'a pas de permission
            // individuelle (la section agit comme un umbrella gate).
            $sectionPermission = $section['permission'] ?? null;
            if (null !== $sectionPermission && !$this->security->isGranted($sectionPermission)) {
                foreach ($section['items'] ?? [] as $item) {
                    if (isset($item['to'])) {
                        $disabledRoutes[] = $item['to'];
                    }
                }

                continue;
            }

            $items = [];
            foreach ($section['items'] ?? [] as $item) {
                $isActive = in_array($item['module'] ?? null, $this->activeModuleIds, true);

                if (!$isActive) {
                    if (isset($item['to'])) {
                        $disabledRoutes[] = $item['to'];
                    }

                    continue;
                }

                // Filtrage par permission RBAC : si l'item declare une permission
                // requise et que l'utilisateur courant ne la possede pas, l'item
                // est masque et sa route ajoutee aux routes desactivees.
                $requiredPermission = $item['permission'] ?? null;
                if (null !== $requiredPermission && !$this->security->isGranted($requiredPermission)) {
                    if (isset($item['to'])) {
                        $disabledRoutes[] = $item['to'];
                    }

                    continue;
                }

                $items[] = [
                    'label' => $item['label'],
                    'to'    => $item['to'],
                    'icon'  => $item['icon'],
                ];
            }

            if ([] === $items) {
                continue;
            }

            $sections[] = [
                'label' => $section['label'],
                'icon'  => $section['icon'],
                'items' => $items,
            ];
        }

        return new SidebarResource($sections, array_values(array_unique($disabledRoutes)));
    }
}
