<?php
declare(strict_types=1);
namespace Aen\MarkdownLab;

use League\CommonMark\Environment\EnvironmentBuilderInterface;
use League\CommonMark\Extension\ExtensionInterface;
use League\CommonMark\Node\Inline\AbstractInline;
use League\CommonMark\Node\Node;
use League\CommonMark\Parser\Inline\InlineParserInterface;
use League\CommonMark\Parser\Inline\InlineParserMatch;
use League\CommonMark\Parser\InlineParserContext;
use League\CommonMark\Renderer\ChildNodeRendererInterface;
use League\CommonMark\Renderer\NodeRendererInterface;
use League\CommonMark\Util\HtmlElement;

final class Note extends AbstractInline
{
    public function __construct(public readonly string $text) { parent::__construct(); }
}

final class NoteParser implements InlineParserInterface
{
    public function getMatchDefinition(): InlineParserMatch
    {
        return InlineParserMatch::regex('\{\{note:([^{}\r\n]{1,160})\}\}');
    }
    public function parse(InlineParserContext $inlineContext): bool
    {
        $text = trim($inlineContext->getMatches()[1]);
        if ($text === '') { return false; }
        $inlineContext->getCursor()->advanceBy($inlineContext->getFullMatchLength());
        $inlineContext->getContainer()->appendChild(new Note($text));
        return true;
    }
}

final class NoteRenderer implements NodeRendererInterface
{
    public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable
    {
        if (!$node instanceof Note) { throw new \InvalidArgumentException('Expected Note'); }
        // HtmlElement accepts already rendered inner HTML: escape the plain note explicitly.
        return new HtmlElement('span', ['class' => 'lab-note', 'role' => 'note'],
            htmlspecialchars($node->text, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'));
    }
}

final class NoteExtension implements ExtensionInterface
{
    public function register(EnvironmentBuilderInterface $environment): void
    {
        $environment->addInlineParser(new NoteParser(), 200);
        $environment->addRenderer(Note::class, new NoteRenderer());
    }
}
