<?php

namespace App\Services;

use App\Models\Document;

class DocumentPreviewService
{
    /**
     * 将文档的 Markdown 内容转换为 HTML 用于预览
     * 统一用于 Filament 后台内联预览和独立预览页面
     *
     * @throws \Exception
     */
    public function convertToHtml(Document $document): string
    {
        return $this->convertMarkdownToHtml($document);
    }

    /**
     * 将 Markdown 转换为 HTML
     *
     * @throws \Exception
     */
    public function convertMarkdownToHtml(Document $document): string
    {
        $markdownContent = $document->getMarkdownContent();

        if (empty($markdownContent)) {
            throw new \Exception('Markdown 内容为空');
        }

        app(DocumentConversionService::class)->ensureMarkdownMediaAssets($document);

        $markdownContent = $this->stripPreviewFrontMatter($markdownContent);
        $markdownContent = $this->rewriteMarkdownMediaPaths($document, $markdownContent);

        $renderService = app(MarkdownRenderService::class);

        return $renderService->render($markdownContent);
    }

    protected function stripPreviewFrontMatter(string $markdownContent): string
    {
        if (!preg_match('/\A---\R(?P<frontmatter>.*?\R)---\R*/s', $markdownContent, $matches)) {
            return $markdownContent;
        }

        $frontMatter = $matches['frontmatter'] ?? '';

        if (!preg_match('/^(author|source_file):/m', $frontMatter)) {
            return $markdownContent;
        }

        return (string) preg_replace('/\A---\R.*?\R---\R*/s', '', $markdownContent, 1);
    }

    protected function rewriteMarkdownMediaPaths(Document $document, string $markdownContent): string
    {
        $documentDir = dirname($document->markdown_path);

        return (string) preg_replace_callback(
            '/!\[(?<alt>[^\]]*)]\((?<path>(?:\.\/)?media\/[^)]+)\)/',
            function (array $matches) use ($documentDir): string {
                $relativePath = trim($matches['path'] ?? '');
                $relativePath = preg_replace('/^\.?\//', '', $relativePath) ?? $relativePath;
                $relativePath = ltrim(str_replace('\\', '/', $relativePath), '/');

                $segments = array_filter(
                    explode('/', $documentDir . '/' . $relativePath),
                    fn (string $segment): bool => $segment !== ''
                );

                $url = '/markdown-media/' . implode('/', array_map('rawurlencode', $segments));

                return sprintf('![%s](%s)', $matches['alt'] ?? '', $url);
            },
            $markdownContent
        );
    }

    /**
     * 检查文档是否可以预览
     */
    public function canPreview(Document $document): bool
    {
        return $document->conversion_status === 'completed'
            && !empty($document->markdown_path);
    }
}
