<?php

namespace App\Service\SnipParser\Markdown;

use App\Repository\SnipRepository;
use App\Service\SnipParser\AbstractParser;
use League\CommonMark\Event\DocumentParsedEvent;
use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
use League\CommonMark\Extension\DefaultAttributes\DefaultAttributesExtension;
use League\CommonMark\Extension\Footnote\FootnoteExtension;
use League\CommonMark\Extension\Table\Table;
use League\CommonMark\GithubFlavoredMarkdownConverter;
use League\CommonMark\Node\Inline\Text;
use League\CommonMark\Node\Query;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Routing\RouterInterface;
use Tempest\Highlight\CommonMark\HighlightExtension;
use Tempest\Highlight\Highlighter;

class MarkdownParser extends AbstractParser
{
    public function __construct(
        #[Autowire(lazy: true)] private readonly RouterInterface $router,
        #[Autowire(lazy: true)] private readonly SnipRepository  $snipRepo,
    ) {}

    public function safeParseView(string $content): string
    {
        $config = [
            'default_attributes' => [
                Table::class => [
                    'class' => 'table table-hover',
                ],
                Link::class => [
                    'class' => 'btn btn-sm btn-secondary',
                ],
            ],
        ];

        $converter = new GithubFlavoredMarkdownConverter($config);
        $converter
            ->getEnvironment()
            ->addExtension(new HighlightExtension(new Highlighter()->withGutter()))
            ->addExtension(new FootnoteExtension())
            ->addExtension(new DefaultAttributesExtension())
            ->addEventListener(DocumentParsedEvent::class, $this->documentParsed(...))
        ;
        return $converter->convert($content);
    }

    private function documentParsed(DocumentParsedEvent $event): void
    {
        $document = $event->getDocument();

        $linkNodes = new Query()
            ->where(Query::type(Link::class))
            ->findAll($document)
        ;

        /** @var Link $linkNode */
        foreach ($linkNodes as $linkNode) {
            $url = $linkNode->getUrl();

            if (!is_numeric($url)) {
                continue;
            }

            $snip = $this->snipRepo->find($url);
            if ($snip === null) {
                continue;
            }
            $linkNode->setUrl($this->router->generate('snip_single', [
                'snip' => $url,
            ]));
            $textNode = $linkNode->firstChild();
            if (!$textNode) {
                $linkNode->appendChild(new Text($snip));
            }
        }
    }
}