<script setup lang="ts">
import { computed, onMounted, onUnmounted, onUpdated, ref } from 'vue'
import MarkdownIt from 'markdown-it'
import mdKatex from '@traptitech/markdown-it-katex'
import mila from 'markdown-it-link-attributes'
import hljs from 'highlight.js'
import { useClipboard } from '@vueuse/core'

interface Props {
  rawTextContent: string
  fontSize?: number | string
  color?: string
}

const props = withDefaults(defineProps<Props>(), {
  rawTextContent: '',
  fontSize: '14px',
  color: '#333',
})

const mkrContainer = ref()
const copyCodeText = ref('')

const { copy: copyTool } = useClipboard({ source: copyCodeText })

const mdi = new MarkdownIt({
  html: true,
  linkify: true,
  highlight(code: any, language: any) {
    const validLang = !!(language && hljs.getLanguage(language))

    if (validLang) {
      const lang = language ?? ''
      return highlightBlock(hljs.highlight(code, { language: lang }).value, lang)
    }

    return highlightBlock(hljs.highlightAuto(code).value, '')
  },
})

mdi.use(mila, { attrs: { target: '_blank', rel: 'noopener' } })
mdi.use(mdKatex, { blockClass: 'katexmath-block rounded-md p-[10px]', errorColor: ' #cc0000' })

const renderTextContent = computed(() => {
  if (props.rawTextContent) {
    const urlRegex = /（(https?:\/\/[^\s]+)）/g
    const rawTextContent = props.rawTextContent.replace(urlRegex, '($1)')
    return mdi.render(rawTextContent)
  }

  return ''
})

const wrapStyle = computed(() => {
  return {
    fontSize: props.fontSize,
    color: props.color,
  }
})

function highlightBlock(str: string, lang?: string) {
  return (
    '<pre class="code-block-wrapper">' +
    '<div class="code-block-header">' +
    `<span class="code-block-header__lang">${lang}</span>` +
    '<span class="code-block-header__copy">复制代码</span>' +
    '</div>' +
    `<code class="hljs code-block-body ${lang}">${str}</code>` +
    '</pre>'
  )
}

function addCopyEvents() {
  if (mkrContainer.value) {
    const copyBtn = mkrContainer.value.querySelectorAll('.code-block-header__copy')
    copyBtn.forEach((btn: HTMLSpanElement) => {
      btn.addEventListener('click', () => {
        const code = btn.parentElement?.nextElementSibling?.textContent
        if (code) {
          copyTool(code).then(() => {
            btn.textContent = '复制成功'

            setTimeout(() => (btn.textContent = '复制代码'), 1000)
          })
        }
      })
    })
  }
}

function removeCopyEvents() {
  if (mkrContainer.value) {
    const copyBtn = mkrContainer.value.querySelectorAll('.code-block-header__copy')
    copyBtn.forEach((btn: HTMLSpanElement) => {
      btn.removeEventListener('click', () => {})
    })
  }
}

onMounted(() => {
  addCopyEvents()
})

onUpdated(() => {
  addCopyEvents()
})

onUnmounted(() => {
  removeCopyEvents()
})
</script>

<template>
  <div ref="mkrContainer" class="markdown-render-container">
    <article class="markdown-body" :style="wrapStyle" v-html="renderTextContent" />
  </div>
</template>

<style lang="scss">
@import './style/highlight.scss';
@import './style/github-markdown.scss';
@import './style/custom-style.scss';
</style>
