<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\PageBuilder\Document;

use CpCreation\VitiCore\PageBuilder\Model\Page;

final class BuilderDocumentRenderer
{
    /**
     * @return list<array<string, mixed>>
     */
    public function documentForLocale(Page $page, string $locale): array
    {
        $documents = $page->getSetting('builderDocumentByLocale', []);
        if (!\is_array($documents)) {
            return [];
        }

        $document = $documents[$locale] ?? null;

        return \is_array($document) ? array_values($document) : [];
    }

    public function renderForLocale(Page $page, string $locale): string
    {
        $document = $this->documentForLocale($page, $locale);
        if ([] === $document) {
            return '';
        }

        return $this->renderNodes($document);
    }

    /**
     * @param list<array<string, mixed>> $nodes
     */
    private function renderNodes(array $nodes): string
    {
        $html = '';
        foreach ($nodes as $node) {
            $html .= $this->renderNode($node);
        }

        return $html;
    }

    /**
     * @param array<string, mixed> $node
     */
    private function renderNode(array $node): string
    {
        if (($node['type'] ?? null) === 'textnode') {
            return htmlspecialchars((string) ($node['content'] ?? ''), \ENT_QUOTES | \ENT_SUBSTITUTE, 'UTF-8');
        }

        $tagName = trim((string) ($node['tagName'] ?? 'div'));
        if (1 !== preg_match('/^[a-z][a-z0-9:-]*$/i', $tagName)) {
            $tagName = 'div';
        }

        $children = \is_array($node['components'] ?? null) ? $node['components'] : [];
        $content = $this->renderNodes(array_values(array_filter($children, \is_array(...))));

        return sprintf(
            '<%1$s%2$s>%3$s</%1$s>',
            $tagName,
            $this->renderAttributes(\is_array($node['attributes'] ?? null) ? $node['attributes'] : []),
            $content,
        );
    }

    /**
     * @param array<string, mixed> $attributes
     */
    private function renderAttributes(array $attributes): string
    {
        $parts = [];
        foreach ($attributes as $name => $value) {
            $name = trim((string) $name);
            if ('' === $name || 1 !== preg_match('/^[@:a-zA-Z_][@:a-zA-Z0-9_.:-]*$/', $name)) {
                continue;
            }

            if (str_starts_with($name, 'data-gjs-') || str_starts_with($name, 'data-highlightable')) {
                continue;
            }

            $parts[] = sprintf(
                ' %s="%s"',
                $name,
                htmlspecialchars((string) $value, \ENT_QUOTES | \ENT_SUBSTITUTE, 'UTF-8'),
            );
        }

        return implode('', $parts);
    }
}
