import MarkdownIt from 'markdown-it'

const markdown = new MarkdownIt({
  html: false,
  linkify: true,
  breaks: true
})

const defaultTableOpen = markdown.renderer.rules.table_open
const defaultTableClose = markdown.renderer.rules.table_close
const defaultParagraphOpen = markdown.renderer.rules.paragraph_open
const defaultLinkOpen = markdown.renderer.rules.link_open
const defaultBlockquoteOpen = markdown.renderer.rules.blockquote_open

const RISK_TEXT_CLASS_BY_LABEL = {
  低风险: 'markdown-risk-text-low',
  中风险: 'markdown-risk-text-medium',
  高风险: 'markdown-risk-text-high'
}

const ACTION_LINK_CLASS_BY_HREF = {
  '#confirm-attachment-association': 'markdown-action-link-confirm',
  '#application-submit': 'markdown-action-link-confirm',
  '#review-next-step': 'markdown-action-link-next',
  '#review-quick-edit': 'markdown-action-link-edit',
  '#review-risk-panel': 'markdown-action-link-risk'
}

function escapeHtml(text) {
  return String(text || '')
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
}

function renderRiskText(text) {
  return escapeHtml(text).replace(/低风险|中风险|高风险/g, (label) => {
    const className = RISK_TEXT_CLASS_BY_LABEL[label]
    return className ? `<span class="${className}">${label}</span>` : label
  })
}

function resolveActionLinkClass(href) {
  const normalizedHref = String(href || '').trim()
  return ACTION_LINK_CLASS_BY_HREF[normalizedHref] || ''
}

function inlineTokenHasActionLink(token) {
  const children = Array.isArray(token?.children) ? token.children : []
  return children.some((child) => (
    child?.type === 'link_open' && resolveActionLinkClass(child.attrGet?.('href'))
  ))
}

function resolveInlineTokenPlainText(token) {
  const children = Array.isArray(token?.children) ? token.children : []
  const childText = children
    .filter((child) => ['text', 'code_inline'].includes(String(child?.type || '')))
    .map((child) => String(child?.content || ''))
    .join('')
    .trim()
  return childText || String(token?.content || '').replace(/[*_`]+/g, '').trim()
}

function blockquoteHasAttachmentHeading(tokens, idx) {
  for (let i = idx + 1; i < tokens.length; i += 1) {
    const token = tokens[i]
    if (token?.type === 'blockquote_close') {
      return false
    }
    if (token?.type === 'inline') {
      return /^附件\s*\d+\s*[：:]/.test(resolveInlineTokenPlainText(token))
    }
  }
  return false
}

markdown.renderer.rules.paragraph_open = (tokens, idx, options, env, self) => {
  if (inlineTokenHasActionLink(tokens[idx + 1])) {
    tokens[idx].attrJoin('class', 'markdown-action-paragraph')
  }
  return defaultParagraphOpen
    ? defaultParagraphOpen(tokens, idx, options, env, self)
    : self.renderToken(tokens, idx, options)
}

markdown.renderer.rules.link_open = (tokens, idx, options, env, self) => {
  const actionClass = resolveActionLinkClass(tokens[idx].attrGet('href'))
  if (actionClass) {
    tokens[idx].attrJoin('class', `markdown-action-link ${actionClass}`)
  }
  return defaultLinkOpen
    ? defaultLinkOpen(tokens, idx, options, env, self)
    : self.renderToken(tokens, idx, options)
}

markdown.renderer.rules.text = (tokens, idx) => renderRiskText(tokens[idx]?.content)

markdown.renderer.rules.blockquote_open = (tokens, idx, options, env, self) => {
  if (blockquoteHasAttachmentHeading(tokens, idx)) {
    tokens[idx].attrJoin('class', 'markdown-attachment-card')
  }
  return defaultBlockquoteOpen
    ? defaultBlockquoteOpen(tokens, idx, options, env, self)
    : self.renderToken(tokens, idx, options)
}

markdown.renderer.rules.table_open = (tokens, idx, options, env, self) => (
  `<div class="markdown-table-wrap">${defaultTableOpen ? defaultTableOpen(tokens, idx, options, env, self) : '<table>'}`
)

markdown.renderer.rules.table_close = (tokens, idx, options, env, self) => (
  `${defaultTableClose ? defaultTableClose(tokens, idx, options, env, self) : '</table>'}</div>`
)

const ALLOWED_COLON_HEADING_TITLES = new Set([
  '基础信息识别结果',
  '报销测算参考',
  '补充信息'
])

function splitColonHeadingLine(line) {
  const rawLine = String(line || '')
  const trimmed = rawLine.trim()
  if (!trimmed || trimmed.startsWith('|') || /^#{1,6}\s/.test(trimmed)) {
    return [rawLine]
  }

  const chineseColonIndex = trimmed.indexOf('：')
  const asciiColonIndex = trimmed.indexOf(':')
  const colonIndexes = [chineseColonIndex, asciiColonIndex].filter((index) => index > 0)
  if (!colonIndexes.length) {
    return [rawLine]
  }

  const colonIndex = Math.min(...colonIndexes)
  const title = trimmed.slice(0, colonIndex + 1)
  const titleText = title.slice(0, -1)
  const body = trimmed.slice(colonIndex + 1).trim()
  if (!ALLOWED_COLON_HEADING_TITLES.has(titleText)) {
    return [rawLine]
  }

  return body ? [`### ${title}`, '', body] : [`### ${title}`]
}

function normalizeColonHeadings(text) {
  const lines = String(text || '').replace(/\r\n?/g, '\n').split('\n')
  const normalizedLines = []
  let inFence = false

  lines.forEach((line) => {
    if (/^\s*(```|~~~)/.test(line)) {
      inFence = !inFence
      normalizedLines.push(line)
      return
    }
    if (inFence) {
      normalizedLines.push(line)
      return
    }

    const nextLines = splitColonHeadingLine(line)
    if (nextLines[0]?.startsWith('### ') && normalizedLines.length) {
      const previousLine = normalizedLines[normalizedLines.length - 1]
      if (String(previousLine || '').trim()) {
        normalizedLines.push('')
      }
    }
    normalizedLines.push(...nextLines)
  })

  return normalizedLines.join('\n').replace(/\n{3,}/g, '\n\n')
}

export function renderMarkdown(text = '') {
  const normalized = normalizeColonHeadings(text).trim()
  return normalized ? markdown.render(normalized) : ''
}
