package me.qwq.doghouse.util;

import com.vladsch.flexmark.util.data.MutableDataSet;
import com.vladsch.flexmark.util.misc.Extension;

import me.qwq.doghouse.flexmark.ext.fancyquote.FancyQuoteExtension;
import me.qwq.doghouse.flexmark.ext.lazyimg.LazyImgNodeRenderer;
import me.qwq.doghouse.flexmark.ext.mermaid.MermaidExtension;
import me.qwq.doghouse.flexmark.ext.plantuml.PlantUMLExtension;

import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.ext.footnotes.FootnoteExtension;
import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension;
import com.vladsch.flexmark.ext.gitlab.GitLabExtension;
import com.vladsch.flexmark.ext.tables.TablesExtension;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

/**
 * Markdown 工具类
 * <p>前台渲染 Post 和 Comment 建议使用 {@link me.qwq.doghouse.service.MarkdownService} 而非此类，方便进行缓存</p>
 * @author Doghole
 */
public class MarkDownUtils {
    
    /**
     * 优先级是从下往上
     */
    private static final List<Extension> POST_EXTENSIONS = Arrays.asList(
            TablesExtension.create(), 
            FootnoteExtension.create(),
            StrikethroughExtension.create(),
            GitLabExtension.create(),
            PlantUMLExtension.create(),         // PlantUML 支持
            MermaidExtension.create(),          // mermaid 后台渲染，需要 node.js 和 mermaid-cli 支持
            FancyQuoteExtension.create()        // 自定义的包裹框，类 VuePress 语法
            );
    
    private static final MutableDataSet COMMENT_SETTINGS = 
        new MutableDataSet()
            .set(HtmlRenderer.SUPPRESSED_LINKS, 
                    "(([jJ][aA][vV][aA])|([vV][bB]))[sS][cC][rR][iI][pP][tT]:.*")
            .set(HtmlRenderer.ESCAPE_HTML, true);

    private static final HtmlRenderer POST_HTML_RENDERER;
    private static final HtmlRenderer COMMENT_HTML_RENDERER;
    private static final Parser POST_PARSER;
    private static final Parser COMMENT_PARSER;
    
    static {

        MutableDataSet options = new MutableDataSet();
        options.set(Parser.EXTENSIONS, POST_EXTENSIONS);
        options.set(PlantUMLExtension.BOTH_MODES, true);
        options.set(HtmlRenderer.SOFT_BREAK, HtmlRenderer.HARD_BREAK.getDefaultValue());
        POST_PARSER = Parser.builder(options).build();
        POST_HTML_RENDERER = HtmlRenderer
                .builder(options)
                .nodeRendererFactory(opts -> new LazyImgNodeRenderer(opts))
                .build();
        options.setAll(COMMENT_SETTINGS);
        COMMENT_PARSER = Parser.builder(options).build();
        COMMENT_HTML_RENDERER = HtmlRenderer
                .builder(options)
                .nodeRendererFactory(opts -> new LazyImgNodeRenderer(opts))
                .build();
        
    }
    
    /**
     * 将 Markdown 格式的 postContent 转换为对应的 html 代码
     * 
     * @param postContent Markdown 格式的文本
     */
    public static String postContentToHtml(String postContent) {
        return mdToHtml(postContent, POST_PARSER, POST_HTML_RENDERER);
    }

    /**
     * 将 Markdown 格式的 postContent 转换为对应的 html 代码
     * <p>
     * 对于包含 &lt!--more--> 分隔符的，取分隔符之前的内容渲染，并拼接 replacementForMore
     * </p>
     * 
     * @param postContent Markdown 格式的文本
     * @param replacementForMore 对 &lt!--more--> 分隔符分隔后拼接的替换项，可以为 html 或 Markdown 格式
     */
    public static String postContentToHtml(String postContent, String replacementForMore) {
        if (replacementForMore != null) {
            int indexOfMore = postContent.toLowerCase().indexOf("<!--more-->");
            if (indexOfMore > -1) {
                postContent = postContent.substring(0, indexOfMore) + replacementForMore;
            }
        }
        return mdToHtml(postContent, POST_PARSER, POST_HTML_RENDERER);
    }
    
    /**
     * 将 Markdown 格式的评论转换为对应的 html 代码
     * @param commentContent
     * @return
     */
    public static String commentToHtml(String commentContent) {
        // 阻止 a 标签中的 javascript/vbscript
        // 阻止内联 HTML
        return mdToHtml(commentContent, COMMENT_PARSER, COMMENT_HTML_RENDERER);
    }
    
    /**
     * 将 Markdown 格式字符串转换为 html 字符串
     * @param markdownString Markdown 格式字符串
     * @param options 额外提供的渲染设置
     * @return
     */
    private static String mdToHtml(String markdownString, Parser parser, HtmlRenderer renderer) {
        if (StringUtils.isEmpty(markdownString)) {
            return "";
        }

        Node document = parser.parse(markdownString);
        String html = renderer.render(document);
        
        // 行号
        // html = html.replaceAll("class=\"(language-.*?)?\\:n\"", "class=\"line-numbers $1\"");
        
        // 为 img 标签添加 lazy
        Document jsoupDoc = Jsoup.parseBodyFragment(html);
        
        // 只处理 <code> 标签
        for (Element code : jsoupDoc.select("code")) {
            String cls = code.className();

            if (cls != null && cls.contains(":n")) {
                // 把 language-xxx:n → "language-xxx line-numbers"
                String newCls = cls.replaceAll(":n", " line-numbers ");
                code.attr("class", newCls.trim());
            }
        }
    
        // 为所有 <img> 添加 lazy 属性
        jsoupDoc.select("img").forEach(img -> {
            if (!img.attr("src").isEmpty()) {
                img.attr("loading", "lazy");
            }
        });
    
        // 返回最终 HTML
        return jsoupDoc.body().html();
    }
}
