<?php

declare(strict_types=1);

final class MyronMarkdownExtractor
{
    public function __construct(
        private readonly MyronHtmlToMarkdownConverter $converter,
        private readonly MyronMarkdownFrontMatterBuilder $frontMatterBuilder,
    ) {
    }

    /**
     * @param array<string, mixed> $page
     * @param array<string, mixed> $context
     */
    public function extract(array $page, array $context = []): string
    {
        $resolvedPath = (string) ($context['resolvedPath'] ?? ($page['path'] ?? '/'));
        $context += $this->defaultRenderContext($page, $resolvedPath);
        $html = myronPublishedPageHtmlAssembler()->assemble($page, $context);
        $bodyHtml = $this->extractBodySectionHtml($html);
        $markdown = $this->converter->convert($bodyHtml, [
            'canonicalUrl' => myronAppUrl() . myronBuildPublicPageUrl($resolvedPath),
        ]);

        return rtrim($this->frontMatterBuilder->build($page), "\n") . "\n\n" . ltrim($markdown);
    }

    /**
     * @param array<string, mixed> $page
     * @return array<string, mixed>
     */
    private function defaultRenderContext(array $page, string $resolvedPath): array
    {
        $navigationByPlacement = myronContentRepository()->listPublishedMenuNavigationByPlacements(['primary'], ['footer']);
        $navigation = is_array($navigationByPlacement['trees']['primary'] ?? null) ? $navigationByPlacement['trees']['primary'] : [];
        $footerNavigation = is_array($navigationByPlacement['flat']['footer'] ?? null) ? $navigationByPlacement['flat']['footer'] : [];

        return [
            'basePath' => myronPublicBasePath(),
            'requestUri' => myronBuildPublicPageUrl($resolvedPath),
            'resolvedPath' => $resolvedPath,
            'navigation' => $navigation,
            'footerNavigation' => $footerNavigation,
            'headerContext' => myronPublicHeaderContextResolver()->resolve($page, $resolvedPath, $navigation),
            'headMetadata' => myronPublicHeadMetadataResolver()->resolvePublishedPage($page),
            'currentUser' => null,
            'channel' => 'admin-preview',
        ];
    }

    private function extractBodySectionHtml(string $html): string
    {
        $doc = new DOMDocument('1.0', 'UTF-8');
        $previous = libxml_use_internal_errors(true);
        $doc->loadHTML('<?xml encoding="UTF-8">' . $html);
        libxml_clear_errors();
        libxml_use_internal_errors($previous);

        foreach ($doc->getElementsByTagName('section') as $section) {
            if (!$section instanceof DOMElement) {
                continue;
            }
            $classes = preg_split('/\s+/', trim($section->getAttribute('class'))) ?: [];
            if (!in_array('myron-public-page__body', $classes, true)) {
                continue;
            }

            $out = '';
            foreach ($section->childNodes as $child) {
                $out .= $doc->saveHTML($child);
            }
            return $out;
        }

        return strip_tags($html);
    }
}
