<?php
declare(strict_types=1);

namespace PpPhp\Core\Designer\Navigation;

final class DesignerNavigationRuntime
{
    private array $operations = [];

    public function createMenu(string $menuId = 'main_menu', string $label = 'Main Menu', string $placement = 'sidebar'): array
    {
        $menu = DesignerNavigationMenu::create($menuId, $label, $placement);
        $this->record('createMenu', ['menuId' => $menuId]);
        return $menu->toComponent();
    }

    public function addItem(array $menuComponent, array $item, ?string $parentId = null): array
    {
        $menu = DesignerNavigationMenu::fromArray((array) ($menuComponent['props'] ?? $menuComponent));
        $menu = $menu->addItem(DesignerNavigationItem::fromArray($item), $parentId);
        $this->record('addItem', ['menuId' => $menu->menuId(), 'item' => $item['id'] ?? '', 'parent' => $parentId]);
        return $menu->toComponent();
    }

    public function removeItem(array $menuComponent, string $itemId): array
    {
        $menu = DesignerNavigationMenu::fromArray((array) ($menuComponent['props'] ?? $menuComponent));
        $menu = $menu->removeItem($itemId);
        $this->record('removeItem', ['menuId' => $menu->menuId(), 'item' => $itemId]);
        return $menu->toComponent();
    }

    public function moveItem(array $menuComponent, string $itemId, int $newIndex): array
    {
        $menu = DesignerNavigationMenu::fromArray((array) ($menuComponent['props'] ?? $menuComponent));
        $menu = $menu->moveItem($itemId, $newIndex);
        $this->record('moveItem', ['menuId' => $menu->menuId(), 'item' => $itemId, 'index' => $newIndex]);
        return $menu->toComponent();
    }

    public function fromPages(string $menuId, array $pages, string $placement = 'sidebar'): array
    {
        $menu = DesignerNavigationMenu::create($menuId, 'Main Menu', $placement);

        foreach ($pages as $page) {
            if (!is_array($page)) {
                continue;
            }
            $menu = $menu->addItem(DesignerNavigationItem::create(
                (string) ($page['pageId'] ?? $page['id'] ?? 'page'),
                (string) ($page['title'] ?? $page['label'] ?? $page['pageId'] ?? 'Page'),
                (string) ($page['pageType'] ?? 'page'),
                (string) ($page['pageId'] ?? $page['id'] ?? 'page'),
                (string) ($page['icon'] ?? '')
            ));
        }

        $this->record('fromPages', ['menuId' => $menuId, 'pages' => count($pages)]);
        return $menu->toComponent();
    }

    public function routesFromPages(array $pages): array
    {
        $routes = [];
        foreach ($pages as $page) {
            if (!is_array($page)) {
                continue;
            }
            $pageId = (string) ($page['pageId'] ?? $page['id'] ?? 'page');
            $routes[] = DesignerRoute::create($pageId . '_route', '/' . str_replace('_', '-', $pageId), $pageId, (string) ($page['title'] ?? $pageId))->toArray();
        }

        $this->record('routesFromPages', ['routes' => count($routes)]);
        return $routes;
    }

    public function applicationShell(string $appId, array $pages): array
    {
        $menu = $this->fromPages($appId . '_main_menu', $pages);
        $routes = $this->routesFromPages($pages);
        $breadcrumb = DesignerBreadcrumb::fromPage('dashboard', 'Dashboard')->toComponent();

        $shell = [
            'version' => '1.0',
            'appId' => $appId,
            'type' => 'application_shell',
            'components' => [
                $menu,
                $breadcrumb,
            ],
            'routes' => $routes,
            'meta' => [
                'designerRuntime' => 'navigation-shell',
                'generatedAt' => date('c'),
            ],
        ];

        $this->record('applicationShell', ['appId' => $appId]);
        return $shell;
    }

    public function render(array $menuComponent): string
    {
        return (new DesignerNavigationRenderer())->render($menuComponent);
    }

    public function validate(array $menuComponent): array
    {
        $props = (array) ($menuComponent['props'] ?? $menuComponent);
        $items = (array) ($props['items'] ?? []);
        $ids = [];
        $issues = [];

        $walk = function (array $items) use (&$walk, &$ids, &$issues): void {
            foreach ($items as $item) {
                $id = (string) ($item['id'] ?? '');
                if ($id === '') {
                    $issues[] = ['item' => '', 'message' => 'Navigation item ID is required'];
                } elseif (in_array($id, $ids, true)) {
                    $issues[] = ['item' => $id, 'message' => 'Duplicate navigation item ID'];
                } else {
                    $ids[] = $id;
                }

                $walk((array) ($item['children'] ?? []));
            }
        };

        $walk($items);

        return [
            'ok' => $issues === [],
            'issues' => $issues,
            'itemCount' => count($ids),
            'placement' => $props['placement'] ?? 'sidebar',
        ];
    }

    public function operations(): array { return $this->operations; }

    public function stats(): array
    {
        return [
            'operations' => count($this->operations),
            'menus' => count(array_filter($this->operations, static fn (array $op): bool => in_array(($op['operation'] ?? ''), ['createMenu', 'fromPages'], true))),
            'itemOperations' => count(array_filter($this->operations, static fn (array $op): bool => in_array(($op['operation'] ?? ''), ['addItem', 'removeItem', 'moveItem'], true))),
            'routeOperations' => count(array_filter($this->operations, static fn (array $op): bool => ($op['operation'] ?? '') === 'routesFromPages')),
        ];
    }

    private function record(string $operation, array $payload): void
    {
        $this->operations[] = [
            'operation' => $operation,
            'payload' => $payload,
            'createdAt' => date('c'),
        ];
    }
}
