import { Marked } from 'marked'
import { markedHighlight } from 'marked-highlight'
import DOMPurify from 'dompurify'
import hljs from 'highlight.js'
import markedKatex, { type MarkedKatexOptions } from 'marked-katex-extension'

const katexOptions: MarkedKatexOptions = {
  throwOnError: false,
  displayMode: true,
  nonStandard: true,
  output: 'html',
}

export function createMarkedInst() {
  return new Marked()
    .use({ gfm: true, async: true, breaks: true })
    .use(
      markedHighlight({
        emptyLangClass: 'hljs',
        langPrefix: 'hljs code-container-wrapper language-',
        highlight(code, lang, _info) {
          const language = hljs.getLanguage(lang) ? lang : 'plaintext'

          // return hljs.highlight(code, { language }).value
          const str = hljs.highlight(code, { language }).value

          // return `<div class="code-render-container"><div class="code-operation-bar-container"><span class="language">${language}</span><span><span class="code-copy-btn iconfont icon-fuzhi"></span><span class="fold-btn iconfont icon-left"></span></span></div><pre class="code-render-inner"><code>${str}</code></pre></div>`

          return (
            '<div class="code-render-container">' +
            '<div class="code-operation-bar-container">' +
            `<span class="language">${language}</span><span><span class="code-copy-btn iconfont icon-fuzhi"></span><span class="fold-btn iconfont icon-left"></span></span>` +
            '</div>' +
            `<div class="code-render-wrapper"><pre class="code-render-inner"><code>${str}</code></pre></div>` +
            '</div>'
          )
        },
      }),
    )
    .use(markedKatex(katexOptions))
    .use({
      hooks: {
        preprocess(markdown: string) {
          /**
           * 1. 将 \(...\) 和 \\(...\\) 转为 $...$ 以支持行内公式
           * 2. 将 \[...\] 和 \\[...\\]  转为 $$...$$ 以支持块级公式
           */

          const katexTextReplace = markdown
            .replace(/\\\\\(|\\\\\)|\\\(|\\\)/g, '$')
            .replace(/\\\\\[|\\\\\]|\\\[|\\\]/g, '$$$$')

          return katexTextReplace
        },
        postprocess(html: string) {
          return DOMPurify.sanitize(html)
        },
      },
    })
}

export function markdownParser(markdown: string) {
  return createMarkedInst().parse(markdown)
}
