<?php

namespace AutoAdmin\Bundle\Menu\Provider;

use AutoAdmin\Bundle\Content\ContentReference\ContentReferenceResolver;
use AutoAdmin\Bundle\Content\Routing\ContentRouter;
use AutoAdmin\Bundle\Menu\Dto\MenuItemDto;
use AutoAdmin\Bundle\Menu\Entity\Menu;
use AutoAdmin\Bundle\Menu\Entity\MenuItem;
use AutoAdmin\Bundle\Menu\Entity\MenuItemTranslation;
use AutoAdmin\Bundle\Menu\Exception\MenuNotFoundException;
use AutoAdmin\Bundle\Menu\Repository\MenuRepository;
use Doctrine\ORM\EntityManagerInterface;
use Twig\Environment;

class MenuProvider
{
    public function __construct(
        protected EntityManagerInterface $entityManager,
        protected ContentReferenceResolver $contentReferenceResolver,
        protected ContentRouter $contentRouter,
        protected Environment $environment
    ) {
    }

    public function get(string $name): MenuItemDto
    {
        $menu = $this->getMenu($name);
        if ($menu !== null && $root = $menu->getRoot()) {
            $item = $this->buildMenuItems($root);
        } else {
            throw new MenuNotFoundException(sprintf('The menu "%s" is not found.', $name));
        }

        return $item;
    }

    protected function buildMenuItems(MenuItem $item, ?MenuItemDto $parent = null): MenuItemDto
    {
        $currentItemNode = $this->convert($item);
        if ($parent !== null) {
            $parent->children[] = $currentItemNode;
        }
        $parent = $currentItemNode;

        if (!empty($item->getChildren())) {
            foreach ($item->getChildren() as $child) {
                $this->buildMenuItems($child, $parent);
            }
        }

        return $parent;
    }

    protected function convert(MenuItem $item): MenuItemDto
    {
        /** @var MenuItemTranslation $itemTranslation */
        $itemTranslation = $item->getCurrentTranslation();
        $itemLabel = '<!-- aa:menu:item-not-translated -->';
        if ($itemTranslation && $label = $itemTranslation->getLabel()) {
            $itemLabel = $label;
        }
        $nodeItem = new MenuItemDto(
            label: $itemLabel,
            isTargetBlank: $item->isTargetBlank(),
            isObfuscated: $item->isObfuscated(),
            display: $item->isDisplay(),
            attributes: $item->getAttributes() ?? [],
        );

        switch ($item->getType()) {
            case MenuItem::TYPE_TEXT:
                break;
            case MenuItem::TYPE_LINK_URL:
                $nodeItem->uri = $item->getUri();
                break;
            case MenuItem::TYPE_LINK_CONTENT:
                // resolve content urls using contentReference
                $content = $this->contentReferenceResolver->resolve($item->getContentReference());
                if ($content) {
                    $action = $item->getContentReference()?->getReferencedAction();
                    $nodeItem->uri = $this->contentRouter->generate($content, $action);
                }

                break;
        }

        return $nodeItem;
    }

    public function doSlugExist(string $name): bool
    {
        return $this->getMenu($name) !== null;
    }

    private function getMenu(string $name): ?Menu
    {
        /** @var MenuRepository $menuRepository */
        $menuRepository = $this->entityManager->getRepository(Menu::class);

        return $menuRepository->contentFindOneBySlug($name);
    }

    public function render(string $menuName): string
    {
        return $this->environment->render('@AutoAdminMenu/menu.html.twig', [
            'menu' => $this->get($menuName),
        ]);
    }
}
