<?php

namespace App\Services;

use League\CommonMark\CommonMarkConverter;
use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
use League\CommonMark\Extension\TaskList\TaskListExtension;
use League\CommonMark\MarkdownConverter;

class MarkdownRenderService
{
    protected MarkdownConverter $converter;
    protected bool $sanitize;

    public function __construct()
    {
        // 从配置文件读取设置
        $this->sanitize = config('documents.markdown.sanitize', true);

        // 创建环境配置
        $config = [
            'html_input' => $this->sanitize ? 'strip' : 'allow', // 根据配置决定是否剥离 HTML 标签
            'allow_unsafe_links' => false, // 不允许不安全的链接
            'max_nesting_level' => 10, // 最大嵌套层级
        ];

        // 创建环境并添加扩展
        $environment = new Environment($config);
        $environment->addExtension(new CommonMarkCoreExtension());
        $environment->addExtension(new TableExtension()); // 支持表格
        $environment->addExtension(new StrikethroughExtension()); // 支持删除线
        $environment->addExtension(new TaskListExtension()); // 支持任务列表

        // 创建转换器
        $this->converter = new MarkdownConverter($environment);
    }

    /**
     * 将 Markdown 内容渲染为 HTML
     * 
     * @param string $markdown Markdown 内容
     * @return string 渲染后的 HTML
     */
    public function render(string $markdown): string
    {
        try {
            // 转换 Markdown 为 HTML
            $html = $this->converter->convert($markdown)->getContent();
            
            // 清理和美化 HTML
            $html = $this->sanitize($html);
            
            return $html;
        } catch (\Exception $e) {
            // 如果渲染失败，返回错误信息
            return '<div class="alert alert-danger">Markdown 渲染失败：' . htmlspecialchars($e->getMessage()) . '</div>';
        }
    }

    /**
     * 清理 HTML 内容，防止 XSS 攻击
     * 
     * @param string $html HTML 内容
     * @return string 清理后的 HTML
     */
    public function sanitize(string $html): string
    {
        // CommonMark 已经配置了 html_input => 'strip'，会自动剥离 HTML 标签
        // 这里我们添加额外的样式包装
        
        $styledHtml = '<div class="markdown-content" style="
            font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, \'Helvetica Neue\', Arial, sans-serif;
            line-height: 1.6;
            color: #333;
            padding: 20px;
            background: white;
            border-radius: 8px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
        ">';
        
        // 添加基本的 Markdown 样式
        $styledHtml .= $this->getMarkdownStyles();
        
        $styledHtml .= $html;
        $styledHtml .= '</div>';

        return $styledHtml;
    }

    /**
     * 获取 Markdown 内容的 CSS 样式
     * 
     * @return string CSS 样式
     */
    protected function getMarkdownStyles(): string
    {
        return '<style>
            .markdown-content h1 { font-size: 2em; margin-top: 0.67em; margin-bottom: 0.67em; font-weight: bold; border-bottom: 1px solid #eee; padding-bottom: 0.3em; }
            .markdown-content h2 { font-size: 1.5em; margin-top: 0.83em; margin-bottom: 0.83em; font-weight: bold; border-bottom: 1px solid #eee; padding-bottom: 0.3em; }
            .markdown-content h3 { font-size: 1.17em; margin-top: 1em; margin-bottom: 1em; font-weight: bold; }
            .markdown-content h4 { font-size: 1em; margin-top: 1.33em; margin-bottom: 1.33em; font-weight: bold; }
            .markdown-content h5 { font-size: 0.83em; margin-top: 1.67em; margin-bottom: 1.67em; font-weight: bold; }
            .markdown-content h6 { font-size: 0.67em; margin-top: 2.33em; margin-bottom: 2.33em; font-weight: bold; }
            .markdown-content p { margin: 1em 0; }
            .markdown-content ul, .markdown-content ol { margin: 1em 0; padding-left: 2em; }
            .markdown-content li { margin: 0.5em 0; }
            .markdown-content code { 
                background-color: #f6f8fa; 
                padding: 2px 6px; 
                border-radius: 3px; 
                font-family: \'SFMono-Regular\', \'Consolas\', \'Liberation Mono\', \'Menlo\', \'Courier\', monospace;
                font-size: 0.9em;
                color: #24292e;
            }
            .markdown-content pre { 
                background-color: #f6f8fa; 
                padding: 16px; 
                border-radius: 6px; 
                overflow-x: auto;
                margin: 1em 0;
                border: 1px solid #e1e4e8;
            }
            .markdown-content pre code { 
                background-color: transparent; 
                padding: 0;
                border: none;
            }
            .markdown-content blockquote { 
                border-left: 4px solid #dfe2e5; 
                padding-left: 16px; 
                margin: 1em 0;
                color: #6a737d;
            }
            .markdown-content table { 
                border-collapse: collapse; 
                width: 100%; 
                margin: 1em 0;
                display: block;
                overflow-x: auto;
            }
            .markdown-content table th, .markdown-content table td { 
                border: 1px solid #dfe2e5; 
                padding: 8px 12px; 
                text-align: left;
            }
            .markdown-content table th { 
                background-color: #f6f8fa; 
                font-weight: bold;
            }
            .markdown-content table tr:nth-child(even) {
                background-color: #f6f8fa;
            }
            .markdown-content a { 
                color: #0366d6; 
                text-decoration: none;
            }
            .markdown-content a:hover { 
                text-decoration: underline;
            }
            .markdown-content hr { 
                border: none; 
                border-top: 2px solid #e1e4e8; 
                margin: 2em 0;
            }
            .markdown-content img { 
                max-width: 100%; 
                height: auto;
                border-radius: 6px;
            }
            .markdown-content del {
                text-decoration: line-through;
                color: #6a737d;
            }
            .markdown-content input[type="checkbox"] {
                margin-right: 0.5em;
            }
        </style>';
    }

    /**
     * 从 Markdown 内容中提取摘要
     * 
     * @param string $markdown Markdown 内容
     * @param int|null $length 摘要长度（字符数），如果为 null 则使用配置文件中的默认值
     * @return string 摘要文本
     */
    public function extractPreview(string $markdown, ?int $length = null): string
    {
        // 如果未指定长度，使用配置文件中的默认值
        if ($length === null) {
            $length = config('documents.markdown.preview_length', 500);
        }

        // 移除 Markdown 标记，获取纯文本
        $text = $this->stripMarkdown($markdown);
        
        // 移除多余的空白字符
        $text = preg_replace('/\s+/', ' ', $text);
        $text = trim($text);
        
        // 截取指定长度
        if (mb_strlen($text) > $length) {
            $text = mb_substr($text, 0, $length) . '...';
        }
        
        return $text;
    }

    /**
     * 移除 Markdown 标记，返回纯文本
     * 
     * @param string $markdown Markdown 内容
     * @return string 纯文本
     */
    protected function stripMarkdown(string $markdown): string
    {
        // 移除代码块
        $text = preg_replace('/```[\s\S]*?```/', '', $markdown);
        $text = preg_replace('/`[^`]+`/', '', $text);
        
        // 移除标题标记
        $text = preg_replace('/^#{1,6}\s+/m', '', $text);
        
        // 移除链接，保留文本
        $text = preg_replace('/\[([^\]]+)\]\([^\)]+\)/', '$1', $text);
        
        // 移除图片
        $text = preg_replace('/!\[([^\]]*)\]\([^\)]+\)/', '', $text);
        
        // 移除粗体和斜体标记
        $text = preg_replace('/\*\*([^\*]+)\*\*/', '$1', $text);
        $text = preg_replace('/\*([^\*]+)\*/', '$1', $text);
        $text = preg_replace('/__([^_]+)__/', '$1', $text);
        $text = preg_replace('/_([^_]+)_/', '$1', $text);
        
        // 移除删除线
        $text = preg_replace('/~~([^~]+)~~/', '$1', $text);
        
        // 移除引用标记
        $text = preg_replace('/^>\s+/m', '', $text);
        
        // 移除列表标记
        $text = preg_replace('/^[\*\-\+]\s+/m', '', $text);
        $text = preg_replace('/^\d+\.\s+/m', '', $text);
        
        // 移除水平线
        $text = preg_replace('/^[\-\*_]{3,}$/m', '', $text);
        
        return $text;
    }
}
