import MarkdownIt from 'markdown-it'
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 rust from 'highlight.js/lib/languages/rust'
import cpp from 'highlight.js/lib/languages/cpp'
import c from 'highlight.js/lib/languages/c'
import php from 'highlight.js/lib/languages/php'
import shell from 'highlight.js/lib/languages/shell'

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],
  ['rust', rust],
  ['cpp', cpp],
  ['c', c],
  ['php', php],
  ['shell', shell],
]

let hljsInstance: HLJSApi | null = null
let mdInstance: MarkdownIt | null = null

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

function buildMarkdownRenderer(hljs: HLJSApi): MarkdownIt {
  const md = new MarkdownIt({
    html: true,
    linkify: true,
    typographer: true,
  })

  md.renderer.rules.heading_open = function (tokens, idx) {
    const token = tokens[idx]
    const contentToken = tokens[idx + 1]
    const title = contentToken ? contentToken.content : ''
    const slug = 'heading-' + title.toLowerCase().replace(/[^\w\u4e00-\u9fa5]+/g, '-') + '-' + idx
    return `<${token.tag} id="${slug}">`
  }

  md.renderer.rules.fence = function (tokens, idx) {
    const token = tokens[idx]
    const info = token.info ? md.utils.unescapeAll(token.info).trim() : ''
    let langName = ''
    let highlighted

    if (info) {
      langName = info.split(/\s+/g)[0]
    }

    if (langName && hljs.getLanguage(langName)) {
      try {
        highlighted = hljs.highlight(token.content, { language: langName, ignoreIllegals: true }).value
      } catch {
        highlighted = md.utils.escapeHtml(token.content)
      }
    } else {
      highlighted = md.utils.escapeHtml(token.content)
    }

    const lines = token.content.trimEnd().split('\n')
    const lineNumbers = lines.map((_, i) => i + 1).join('\n')

    const copyIconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: block;"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>`

    return `
    <div class="ios-code-container w-full max-w-full my-6 md:my-10 rounded-lg md:rounded-xl overflow-hidden shadow-2xl bg-[#1e1e1e] border border-white/5 relative group/code text-sm">
      <div class="mac-window-header flex items-center justify-between px-3 md:px-4 py-2 md:py-3 bg-[#282828] border-b border-white/5">
        <div class="flex items-center gap-3 md:gap-4">
          <div class="flex gap-1.5 md:gap-2">
            <div class="w-2.5 h-2.5 md:w-3 md:h-3 rounded-full bg-[#ff5f56]"></div>
            <div class="w-2.5 h-2.5 md:w-3 md:h-3 rounded-full bg-[#ffbd2e]"></div>
            <div class="w-2.5 h-2.5 md:w-3 md:h-3 rounded-full bg-[#27c93f]"></div>
          </div>
          <div class="text-[10px] md:text-xs text-white/30 font-mono select-none uppercase tracking-wider">${langName || 'TEXT'}</div>
        </div>
        <button class="copy-btn flex items-center gap-1.5 px-2 py-1 rounded hover:bg-white/10 transition-all cursor-pointer opacity-100" aria-label="Copy code">
          <span class="text-white/70">${copyIconSvg}</span>
          <span class="text-[10px] md:text-xs text-white/70 font-medium">复制</span>
        </button>
      </div>
      <div class="code-content-wrapper flex min-w-0 max-w-full">
        <div class="line-numbers-wrapper hidden md:block select-none text-right border-r border-white/5 bg-[#1e1e1e] py-3 md:py-4 px-2 md:px-3 min-w-[2.5rem] md:min-w-[3rem] text-white/20">
          <pre class="font-mono text-xs md:text-sm leading-relaxed" style="margin:0;">${lineNumbers}</pre>
        </div>
        <div class="code-block-wrapper flex-1 py-3 md:py-4 px-3 md:px-4 bg-[#1e1e1e] min-w-0 w-full" style="overflow-x: auto; -webkit-overflow-scrolling: touch;">
          <pre class="hljs !bg-transparent !m-0 !p-0 !rounded-none !overflow-visible"><code class="!font-mono text-xs md:text-sm leading-relaxed block" style="white-space: pre;">${highlighted}</code></pre>
        </div>
      </div>
    </div>
  `
  }

  return md
}

function getMarkdownRenderer(): MarkdownIt {
  if (!mdInstance) {
    mdInstance = buildMarkdownRenderer(getHljs())
  }
  return mdInstance
}

export async function renderMarkdown(content: string): Promise<string> {
  if (!content) return ''
  const md = getMarkdownRenderer()
  return md.render(content)
}

/** 预加载 highlight.js（可在路由进入详情页时调用） */
export function preloadMarkdownRenderer(): void {
  getHljs()
}
