<?php

declare(strict_types=1);

namespace Builder\Core\Foundation\Navigation;

use Builder\Core\Foundation\Definition\MenuItem;
use Builder\Core\Foundation\Registry;
use Builder\Core\Foundation\Settings\BuilderSettings;

final class NavigationBuilder
{
    public function __construct(private readonly Registry $registry) {}

    /**
     * Build the navigation array for the given user permissions.
     *
     * @param  list<string>  $permissions
     * @return list<array<string, mixed>>
     */
    public function build(array $permissions): array
    {
        $menuItems = array_values(array_filter(
            $this->registry->menuItems(),
            fn (MenuItem $item): bool => $item->getPermission() === null
                || in_array('*', $permissions, true)
                || in_array($item->getPermission(), $permissions, true),
        ));

        $items = array_map(
            fn (MenuItem $item): array => $item->toArrayForUser($permissions),
            $menuItems,
        );

        $this->injectSettingsPageItems($items, $permissions);

        return $items;
    }

    /**
     * Prepend registered settings pages as sidebar children of the Settings menu item.
     *
     * @param  list<array<string, mixed>>  $items
     * @param  list<string>  $permissions
     */
    private function injectSettingsPageItems(array &$items, array $permissions): void
    {
        $settingsIndex = array_search('settings', array_column($items, 'key'));

        if ($settingsIndex === false) {
            return;
        }

        $settingsChildren = $this->buildSettingsPageItems($permissions);

        /** @var int $settingsIndex */
        $items[$settingsIndex]['children'] = array_merge(
            $settingsChildren,
            $items[$settingsIndex]['children'],
        );
    }

    /**
     * Build nav items for each accessible registered settings page.
     *
     * @param  list<string>  $permissions
     * @return list<array<string, mixed>>
     */
    private function buildSettingsPageItems(array $permissions): array
    {
        $pages = array_filter(
            $this->registry->settingsPages(),
            fn (BuilderSettings $page): bool => $page->navGroup() === 'settings',
        );

        return array_values(array_filter(
            array_map(
                fn (BuilderSettings $page): array => [
                    'key' => $page->getKey(),
                    'label' => $page->getLabel(),
                    'icon' => null,
                    'route' => $page->getParent() !== null
                        ? route('builder.settings.show.sub', [$page->getParent(), $page->getKey()])
                        : route('builder.settings.show', $page->getKey()),
                    'children' => [],
                    'permission' => $page->getPermission(),
                ],
                $pages,
            ),
            fn (array $item): bool => $item['permission'] === null
                || in_array('*', $permissions, true)
                || in_array($item['permission'], $permissions, true),
        ));
    }
}
