/**
 * AI 聊天气泡：将 Markdown 转为 mp-html 可渲染的 HTML
 * iOS App 的 rich-text 对 rpx、h1~h6(2em) 支持差，统一用 px + p 标签
 */

const FONT = {
  body: 14,
  bodySm: 12,
  h1: 15,
  h2: 14.5,
  h3: 14
}

function px(n) {
  return `${n}px`
}

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

/** 已是 HTML 片段时不再二次转义 */
function looksLikeHtml(s) {
  return /<\/?[a-z][\s\S]*>/i.test(s)
}

/** iOS rich-text：h1~h6 改为 p+px，去掉 font/big 等会放大的标签 */
function normalizeAiHtml(html) {
  let s = String(html)
  const headingPx = [FONT.h1, FONT.h2, FONT.h3, FONT.h3, FONT.h3, FONT.h3]
  for (let level = 1; level <= 6; level += 1) {
    const size = headingPx[level - 1]
    const re = new RegExp(`<h${level}(\\s[^>]*)?>([\\s\\S]*?)</h${level}>`, 'gi')
    s = s.replace(
      re,
      (_, _attrs, content) =>
        `<p style="margin:8px 0 6px;font-size:${px(size)};font-weight:600;line-height:1.35;word-break:break-word;">${content}</p>`
    )
  }
  s = s.replace(/<font\b[^>]*>/gi, '<span>').replace(/<\/font>/gi, '</span>')
  s = s.replace(/<big\b[^>]*>/gi, '<span>').replace(/<\/big>/gi, '</span>')
  return s
}

/**
 * @param {string} text 原始 Markdown 或纯文本
 * @returns {string} HTML
 */
export function markdownToHtml(text) {
  if (text == null || text === '') {
    return ''
  }
  const raw = String(text)
  if (looksLikeHtml(raw)) {
    return normalizeAiHtml(raw)
  }

  const blocks = []
  const re = /```([\s\S]*?)```/g
  let last = 0
  let m
  while ((m = re.exec(raw)) !== null) {
    if (m.index > last) {
      blocks.push({ type: 'md', text: raw.slice(last, m.index) })
    }
    blocks.push({ type: 'code', text: m[1] })
    last = m.index + m[0].length
  }
  if (last < raw.length) {
    blocks.push({ type: 'md', text: raw.slice(last) })
  }
  if (!blocks.length) {
    blocks.push({ type: 'md', text: raw })
  }

  return blocks.map((b) => (b.type === 'code' ? formatCodeBlock(b.text) : formatMdBlock(b.text))).join('')
}

function formatCodeBlock(code) {
  const body = escapeHtml(code.replace(/^\n|\n$/g, ''))
  return `<pre style="margin:8px 0;padding:10px 12px;border-radius:8px;background:#f6f8fa;overflow-x:auto;font-size:${px(
    FONT.bodySm
  )};line-height:1.45"><code>${body}</code></pre>`
}

function headingStyle(level) {
  const size = level === 1 ? FONT.h1 : level === 2 ? FONT.h2 : FONT.h3
  return `margin:8px 0 6px;font-size:${px(size)};font-weight:600;line-height:1.35;word-break:break-word;`
}

function formatMdBlock(text) {
  const lines = text.split('\n')
  const out = []
  let i = 0

  while (i < lines.length) {
    const line = lines[i]
    const trimmed = line.trim()

    if (!trimmed) {
      i += 1
      continue
    }

    if (/^#{1,3}\s+/.test(trimmed)) {
      const level = trimmed.match(/^(#+)/)[1].length
      const content = inlineFormat(escapeHtml(trimmed.replace(/^#+\s+/, '')))
      out.push(`<p style="${headingStyle(level)}">${content}</p>`)
      i += 1
      continue
    }

    if (/^[-*]\s+/.test(trimmed)) {
      const items = []
      while (i < lines.length && /^[-*]\s+/.test(lines[i].trim())) {
        items.push(inlineFormat(escapeHtml(lines[i].trim().replace(/^[-*]\s+/, ''))))
        i += 1
      }
      out.push(
        `<ul style="margin:6px 0 12px;padding-left:1.25em;font-size:${px(FONT.body)}">${items
          .map((li) => `<li style="margin:4px 0;line-height:1.5;font-size:${px(FONT.body)}">${li}</li>`)
          .join('')}</ul>`
      )
      continue
    }

    if (/^\d+\.\s+/.test(trimmed)) {
      const items = []
      while (i < lines.length && /^\d+\.\s+/.test(lines[i].trim())) {
        items.push(inlineFormat(escapeHtml(lines[i].trim().replace(/^\d+\.\s+/, ''))))
        i += 1
      }
      out.push(
        `<ol style="margin:6px 0 12px;padding-left:1.25em;font-size:${px(FONT.body)}">${items
          .map((li) => `<li style="margin:4px 0;line-height:1.5;font-size:${px(FONT.body)}">${li}</li>`)
          .join('')}</ol>`
      )
      continue
    }

    if (/^>\s+/.test(trimmed)) {
      const quoteLines = []
      while (i < lines.length && /^>\s?/.test(lines[i].trim())) {
        quoteLines.push(lines[i].trim().replace(/^>\s?/, ''))
        i += 1
      }
      const body = quoteLines.map((l) => inlineFormat(escapeHtml(l))).join('<br/>')
      out.push(
        `<blockquote style="margin:8px 0;padding:6px 12px;border-left:4px solid #22c55e;background:rgba(255,255,255,0.55);font-size:${px(
          FONT.body
        )}">${body}</blockquote>`
      )
      continue
    }

    const para = []
    while (i < lines.length && lines[i].trim()) {
      para.push(lines[i])
      i += 1
    }
    const body = inlineFormat(escapeHtml(para.join('\n'))).replace(/\n/g, '<br/>')
    out.push(
      `<p style="margin:0 0 10px;line-height:1.55;word-break:break-word;font-size:${px(FONT.body)}">${body}</p>`
    )
  }

  return (
    out.join('') ||
    `<p style="margin:0;line-height:1.55;font-size:${px(FONT.body)}">${inlineFormat(escapeHtml(text))}</p>`
  )
}

function inlineFormat(s) {
  return s
    .replace(
      /`([^`]+)`/g,
      `<code style="padding:2px 6px;border-radius:4px;background:rgba(0,0,0,0.06);font-size:${px(FONT.bodySm)}">$1</code>`
    )
    .replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
    .replace(/\*([^*]+)\*/g, '<em>$1</em>')
}

const bodyStyle = `font-size:${px(FONT.body)};line-height:1.55;word-break:break-word;`

/** mp-html tag-style（统一 px，避免 iOS rich-text 忽略 rpx） */
export const MP_HTML_TAG_STYLE = {
  p: `margin:0 0 10px;${bodyStyle}`,
  div: bodyStyle,
  h1: `display:block;margin:8px 0 6px;font-size:${px(FONT.h1)};font-weight:600;line-height:1.35;`,
  h2: `display:block;margin:8px 0 6px;font-size:${px(FONT.h2)};font-weight:600;line-height:1.35;`,
  h3: `display:block;margin:8px 0 6px;font-size:${px(FONT.h3)};font-weight:600;line-height:1.35;`,
  h4: `display:block;margin:8px 0 4px;font-size:${px(FONT.h3)};font-weight:600;line-height:1.35;`,
  h5: `display:block;margin:6px 0 4px;font-size:${px(FONT.h3)};font-weight:600;line-height:1.35;`,
  h6: `display:block;margin:6px 0 4px;font-size:${px(FONT.h3)};font-weight:600;line-height:1.35;`,
  ul: `margin:6px 0 12px;padding-left:1.25em;font-size:${px(FONT.body)};`,
  ol: `margin:6px 0 12px;padding-left:1.25em;font-size:${px(FONT.body)};`,
  li: `margin:4px 0;line-height:1.5;font-size:${px(FONT.body)};`,
  pre: `margin:8px 0;padding:10px 12px;border-radius:8px;background:#f6f8fa;overflow-x:auto;font-size:${px(FONT.bodySm)};`,
  code: `font-family:monospace;font-size:${px(FONT.bodySm)};`,
  blockquote: `margin:8px 0;padding:6px 12px;border-left:4px solid #22c55e;background:rgba(255,255,255,0.55);font-size:${px(
    FONT.body
  )};`,
  a: `color:#16a34a;text-decoration:underline;font-size:${px(FONT.body)};`,
  strong: 'font-weight:600;',
  em: 'font-style:italic;',
  big: `display:inline;font-size:${px(FONT.body)};`,
  small: `display:inline;font-size:${px(FONT.bodySm)};`,
  table: `border-collapse:collapse;margin:8px 0;font-size:${px(FONT.bodySm)};max-width:100%;`,
  th: `border:1px solid #ddd4c8;padding:6px 10px;background:#f0ebe3;font-size:${px(FONT.bodySm)};`,
  td: `border:1px solid #ddd4c8;padding:6px 10px;font-size:${px(FONT.bodySm)};`
}

export const MP_HTML_CONTAINER_STYLE = `display:block;width:100%;min-width:0;overflow:visible;line-height:1.55;font-size:${px(
  FONT.body
)};color:#4a4542;word-break:break-word;-webkit-text-size-adjust:100%;text-size-adjust:100%;`
