/**
 * Markdown 渲染：marked + 树摇 highlight.js。
 * 放在 content/lib（勿用分包 utils，会与主包 utils 撞路径导致 ENOENT）。
 * 不做行号（对齐 PC 移动端）。
 */
import { marked, type Tokens } from 'marked'
import type { HLJSApi, LanguageFn } from 'highlight.js'
import hljsCore from 'highlight.js/lib/core'
import javascript from 'highlight.js/lib/languages/javascript'
import typescript from 'highlight.js/lib/languages/typescript'
import python from 'highlight.js/lib/languages/python'
import go from 'highlight.js/lib/languages/go'
import java from 'highlight.js/lib/languages/java'
import css from 'highlight.js/lib/languages/css'
import xml from 'highlight.js/lib/languages/xml'
import json from 'highlight.js/lib/languages/json'
import bash from 'highlight.js/lib/languages/bash'
import sql from 'highlight.js/lib/languages/sql'
import yaml from 'highlight.js/lib/languages/yaml'
import markdown from 'highlight.js/lib/languages/markdown'
import { resolveHighlightLanguage } from './codeHighlight'
import { rewriteHtmlMediaUrls } from '@/utils/request'

const LANGUAGE_REGISTRY: Array<[string, LanguageFn]> = [
  ['javascript', javascript],
  ['typescript', typescript],
  ['python', python],
  ['go', go],
  ['java', java],
  ['css', css],
  ['xml', xml],
  ['html', xml],
  ['json', json],
  ['bash', bash],
  ['sh', bash],
  ['sql', sql],
  ['yaml', yaml],
  ['yml', yaml],
  ['markdown', markdown],
  ['md', markdown],
]

let hljsInstance: HLJSApi | null = null
let markedReady = false

function getHljs(): HLJSApi {
  if (!hljsInstance) {
    hljsInstance = hljsCore
    for (const [name, register] of LANGUAGE_REGISTRY) {
      hljsInstance.registerLanguage(name, register)
    }
  }
  return hljsInstance
}

/** 转义 HTML，避免未高亮代码注入 */
function escapeHtml(text: string): string {
  return text
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
}

/**
 * 单段代码 → 带 Mac 风格头栏的 HTML（供 mp-html）
 */
export function highlightCodeBlock(code: string, language?: string): string {
  const hljs = getHljs()
  const lang = resolveHighlightLanguage(language)
  let highlighted: string
  if (lang && lang !== 'plaintext' && hljs.getLanguage(lang)) {
    try {
      highlighted = hljs.highlight(code, { language: lang, ignoreIllegals: true }).value
    }
    catch {
      highlighted = escapeHtml(code)
    }
  }
  else {
    highlighted = escapeHtml(code)
  }
  const label = (lang && lang !== 'plaintext' ? lang : 'TEXT').toUpperCase()
  return `
<div class="ios-code-container">
  <div class="mac-window-header">
    <div class="mac-dots">
      <span class="dot red"></span><span class="dot yellow"></span><span class="dot green"></span>
    </div>
    <span class="mac-lang">${label}</span>
  </div>
  <pre class="hljs code-pre"><code class="hljs">${highlighted}</code></pre>
</div>`
}

function ensureMarked() {
  if (markedReady) return
  const renderer = new marked.Renderer()
  renderer.code = ({ text, lang }: Tokens.Code) => highlightCodeBlock(text, lang || '')
  marked.setOptions({
    gfm: true,
    breaks: false,
  })
  marked.use({ renderer })
  markedReady = true
}

/** 渲染 Markdown 为 HTML（含代码高亮块）；相对图片路径拼上传域名 */
export async function renderMarkdown(content: string): Promise<string> {
  if (!content) return ''
  getHljs()
  ensureMarked()
  const html = marked.parse(content) as string
  return rewriteHtmlMediaUrls(html)
}

/** 预加载 highlight（进入详情/弹层前可调用） */
export function preloadMarkdownRenderer(): void {
  getHljs()
}
