<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\PageBuilder\Routing;

use CpCreation\VitiCore\PageBuilder\Document\BuilderDocumentManager;
use CpCreation\VitiCore\PageBuilder\Model\Page;
use Twig\Environment;

final readonly class RouteTemplatePageImporter
{
    /**
     * @var array<string, string>
     */
    private const ROUTE_TEMPLATE_MAP = [
        'homepage' => 'homepage.html.twig',
    ];

    public function __construct(
        private Environment $twig,
        private BuilderDocumentManager $builderDocumentManager,
    ) {
    }

    public function import(Page $page, string $locale): void
    {
        $routeName = trim((string) $page->getRouteName());
        if (!isset(self::ROUTE_TEMPLATE_MAP[$routeName])) {
            return;
        }

        $html = $this->twig->render(self::ROUTE_TEMPLATE_MAP[$routeName], [
            'pageBuilderMode' => false,
            'pageImportLocale' => $locale,
        ]);

        $document = $this->builderDocumentManager->normalizeDocument($this->parseMainDocument($html));
        if ([] === $document) {
            return;
        }

        $documents = $page->getSetting('builderDocumentByLocale', []);
        $documents = \is_array($documents) ? $documents : [];
        $documents[$locale] = $document;

        $page->setSetting('builderDocumentByLocale', $documents);
        $page->setSetting('builderImportedFromTemplate', $routeName);
        $page->setSetting('builderImportedAt', (new \DateTimeImmutable())->format(\DATE_ATOM));
    }

    /**
     * @return list<array<string, mixed>>
     */
    private function parseMainDocument(string $html): array
    {
        $previous = libxml_use_internal_errors(true);
        $document = new \DOMDocument('1.0', 'UTF-8');
        $document->loadHTML($html, \LIBXML_HTML_NOIMPLIED | \LIBXML_HTML_NODEFDTD);
        libxml_clear_errors();
        libxml_use_internal_errors($previous);

        $xpath = new \DOMXPath($document);
        $main = $xpath->query('//main')->item(0);
        if (!$main instanceof \DOMElement) {
            return [];
        }

        $nodes = [];
        foreach ($main->childNodes as $child) {
            $parsed = $this->parseNode($child);
            if (null !== $parsed) {
                $nodes[] = $parsed;
            }
        }

        return $nodes;
    }

    /**
     * @return array<string, mixed>|null
     */
    private function parseNode(\DOMNode $node): ?array
    {
        if ($node instanceof \DOMText) {
            $content = $node->textContent ?? '';
            if ('' === trim($content)) {
                return null;
            }

            return [
                'type' => 'textnode',
                'content' => $content,
            ];
        }

        if (!$node instanceof \DOMElement) {
            return null;
        }

        if (\in_array(strtolower($node->tagName), ['script'], true)) {
            return null;
        }

        $children = [];
        foreach ($node->childNodes as $child) {
            $parsedChild = $this->parseNode($child);
            if (null !== $parsedChild) {
                $children[] = $parsedChild;
            }
        }

        return [
            'type' => 'default',
            'tagName' => strtolower($node->tagName),
            'attributes' => $this->extractAttributes($node),
            'components' => $children,
        ];
    }

    /**
     * @return array<string, string>
     */
    private function extractAttributes(\DOMElement $element): array
    {
        $attributes = [];
        foreach ($element->attributes as $attribute) {
            $name = trim((string) $attribute->nodeName);
            if ('' === $name) {
                continue;
            }

            if (str_starts_with($name, 'data-viti-builder') || 'data-viti-field' === $name) {
                continue;
            }

            $attributes[$name] = (string) $attribute->nodeValue;
        }

        return $attributes;
    }
}
