import MarkdownIt from 'markdown-it'
import {
  DOCUMENT_DETAIL_HREF_PREFIX,
  extractTrustedHtmlBlocks,
  normalizeConversationText,
  restoreTrustedHtmlBlocks
} from './conversationTrustedHtml.js'

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()
  if (normalizedHref.startsWith(DOCUMENT_DETAIL_HREF_PREFIX)) {
    return 'markdown-action-link-document'
  }
  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>`
)

export function renderMarkdown(text = '') {
  const { content, trustedHtmlBlocks } = extractTrustedHtmlBlocks(text)
  const normalized = normalizeConversationText(content).trim()
  return normalized ? restoreTrustedHtmlBlocks(markdown.render(normalized), trustedHtmlBlocks) : ''
}
