import { Marked } from 'marked'
import type { CSSProperties } from 'react'
import type { Tokens } from 'marked'

// 将样式对象转换为 CSS 字符串
function cssPropertiesToString(style: StyleOptions = {}): string {
  return Object.entries(style)
    .filter(([_, value]) => value !== undefined)
    .map(([key, value]) => {
      // 转换驼峰命名为连字符命名
      const cssKey = key.replace(/([A-Z])/g, '-$1').toLowerCase()
      return `${cssKey}: ${value}`
    })
    .join(';')
}

// 将基础样式选项转换为 CSS 字符串
function baseStylesToString(base: RendererOptions['base'] = {}): string {
  const styles: string[] = []

  if (base.lineHeight) {
    styles.push(`line-height: ${base.lineHeight}`)
  }
  if (base.fontSize) {
    styles.push(`font-size: ${base.fontSize}`)
  }

  return styles.join(';')
}

// 预处理函数
function preprocessMarkdown(markdown: string): string {
  return markdown
    // 处理 ** 语法,但排除已经是 HTML 的部分
    .replace(/(?<!<[^>]*)\*\*([^*]+)\*\*(?![^<]*>)/g, '<strong>$1</strong>')
    // 处理无序列表的 - 标记,但排除代码块内的部分
    .replace(/^(?!\s*```)([ \t]*)-\s+/gm, '$1• ')
}

// Initialize marked instance
const marked = new Marked()

// 创建基础渲染器
const baseRenderer = new marked.Renderer()

// 重写 strong 渲染器
baseRenderer.strong = function(text) {
  return `<strong>${text}</strong>`
}

// 应用配置和渲染器
marked.setOptions({
  gfm: true,
  breaks: true,
  async: false,
  pedantic: false,
  renderer: baseRenderer
})

const defaultOptions: RendererOptions = {
  base: {
    primaryColor: '#333333',
    textAlign: 'left',
    lineHeight: '1.75',
    fontSize: '15px',
    themeColor: '#1a1a1a'
  },
  block: {
    h1: { fontSize: '24px' },
    h2: { fontSize: '20px' },
    h3: { fontSize: '18px' },
    p: { fontSize: '15px', color: '#333333' },
    code_pre: { fontSize: '14px', color: '#333333' },
    blockquote: { fontSize: '15px', color: '#666666' }
  },
  inline: {
    link: { color: '#576b95' },
    codespan: { color: '#333333' },
    em: { color: '#666666' }
  }
}

export function convertToWechat(markdown: string, options: RendererOptions = defaultOptions): string {
  const renderer = new marked.Renderer()
  
  // 继承基础渲染器
  Object.setPrototypeOf(renderer, baseRenderer)

  // 合并选项
  const mergedOptions = {
    base: { ...defaultOptions.base, ...options.base },
    block: { ...defaultOptions.block, ...options.block },
    inline: { ...defaultOptions.inline, ...options.inline }
  }

  renderer.heading = function({ text, depth }: Tokens.Heading) {
    const style = {
      ...mergedOptions.block?.[`h${depth}`],
      color: mergedOptions.base?.themeColor, // 使用主题颜色
      textAlign: mergedOptions.base?.textAlign // 添加文本对齐
    }
    const styleStr = cssPropertiesToString(style)
    const tokens = marked.Lexer.lexInline(text)
    const content = marked.Parser.parseInline(tokens, { renderer })
    return `<h${depth}${styleStr ? ` style="${styleStr}"` : ''}>${content}</h${depth}>`
  }

  renderer.paragraph = function({ text }: Tokens.Paragraph) {
    const style = mergedOptions.block?.p || {}
    const styleStr = cssPropertiesToString(style)
    const tokens = marked.Lexer.lexInline(text)
    const content = marked.Parser.parseInline(tokens, { renderer })
    return `<p style="${styleStr}">${content}</p>`
  }

  renderer.blockquote = function({ text }: Tokens.Blockquote) {
    const style = mergedOptions.block?.blockquote
    const styleStr = cssPropertiesToString(style)
    return `<blockquote${styleStr ? ` style="${styleStr}"` : ''}>${text}</blockquote>`
  }

  renderer.code = function({ text, lang }: Tokens.Code) {
    const style = mergedOptions.block?.code_pre
    const styleStr = cssPropertiesToString(style)
    return `<pre${styleStr ? ` style="${styleStr}"` : ''}><code class="language-${lang || ''}">${text}</code></pre>`
  }

  renderer.codespan = function({ text }: Tokens.Codespan) {
    const style = mergedOptions.inline?.codespan
    const styleStr = cssPropertiesToString(style)
    return `<code${styleStr ? ` style="${styleStr}"` : ''}>${text}</code>`
  }

  renderer.em = function({ text }: Tokens.Em) {
    const style = mergedOptions.inline?.em
    const styleStr = cssPropertiesToString(style)
    return `<em${styleStr ? ` style="${styleStr}"` : ''}>${text}</em>`
  }

  renderer.strong = function({ text }: Tokens.Strong) {
    const style = mergedOptions.inline?.strong
    const styleStr = cssPropertiesToString(style)
    return `<strong${styleStr ? ` style="${styleStr}"` : ''}>${text}</strong>`
  }

  renderer.link = function({ href, title, text }: Tokens.Link) {
    const style = mergedOptions.inline?.link
    const styleStr = cssPropertiesToString(style)
    return `<a href="${href}"${title ? ` title="${title}"` : ''}${styleStr ? ` style="${styleStr}"` : ''}>${text}</a>`
  }

  renderer.image = function({ href, title, text }: Tokens.Image) {
    const style = mergedOptions.block?.image
    const styleStr = cssPropertiesToString(style)
    return `<img src="${href}"${title ? ` title="${title}"` : ''} alt="${text}"${styleStr ? ` style="${styleStr}"` : ''} />`
  }

// 重写 list 方法
renderer.list = function(token: Tokens.List): string {
    const tag = token.ordered ? 'ol' : 'ul'
    try {
      const style = mergedOptions.block?.[token.ordered ? 'ol' : 'ul']
      const styleStr = cssPropertiesToString(style)
      const startAttr = token.ordered && token.start !== 1 ? ` start="${token.start}"` : ''
      
      return `<${tag}${startAttr}${styleStr ? ` style="${styleStr}"` : ''}>${token.items.map(item => renderer.listitem(item)).join('')}</${tag}>`
    } catch (error) {
      console.error(`Error rendering list: ${error}`)
      return `<${tag}>${token.items.map(item => renderer.listitem(item)).join('')}</${tag}>`
    }
}

// 重写 listitem 方法
renderer.listitem = function(item: Tokens.ListItem) {
    try {
      const style = mergedOptions.inline?.listitem
      const styleStr = cssPropertiesToString(style)
      
      // 移除列表项开头的破折号和空格
      let itemText = item.text.replace(/^- /, '')
      
      // 处理任务列表项
      if (item.task) {
        const checkbox = `<input type="checkbox"${item.checked ? ' checked=""' : ''} disabled="" /> `
        itemText = checkbox + itemText
      }
      
      // 使用 Lexer 和 Parser 处理剩余的内联标记
      const tokens = marked.Lexer.lexInline(itemText)
      const content = marked.Parser.parseInline(tokens, { renderer })
      
      return `<li${styleStr ? ` style="${styleStr}"` : ''}>${content}</li>`
    } catch (error) {
      console.error(`Error rendering list item: ${error}`)
      return `<li>${item.text}</li>`
    }
  }
  
  // Convert Markdown to HTML using the custom renderer
  const html = marked.parse(markdown, { renderer }) as string

  // Apply base styles
  const baseStyles = baseStylesToString(mergedOptions.base)
  return baseStyles ? `<section style="${baseStyles}">${html}</section>` : html
}

export function convertToXiaohongshu(markdown: string): string {
  // 预处理 markdown
  markdown = preprocessMarkdown(markdown)

  const renderer = new marked.Renderer()
  
  // 自定义渲染规则
  renderer.heading = function({ text, depth }: Tokens.Heading) {
    const fontSize = {
      [1]: '20px',
      [2]: '18px',
      [3]: '16px',
      [4]: '15px',
      [5]: '14px',
      [6]: '14px'
    }[depth] || '14px'

    return `<h${depth} style="margin-top: 25px; margin-bottom: 12px; font-weight: bold; font-size: ${fontSize}; color: #222;">${text}</h${depth}>`
  }

  renderer.paragraph = function({ text }: Tokens.Paragraph) {
    return `<p style="margin-bottom: 16px; line-height: 1.6; font-size: 15px; color: #222;">${text}</p>`
  }

  // 使用自定义渲染器转换 Markdown
  return marked.parse(markdown, { renderer }) as string
}

export interface StyleOptions {
  fontSize?: string
  color?: string
  margin?: string
  padding?: string
  border?: string
  borderLeft?: string
  borderBottom?: string
  borderRadius?: string
  background?: string
  fontWeight?: string
  fontStyle?: string
  textDecoration?: string
  display?: string
  lineHeight?: string | number
  textAlign?: string
  paddingLeft?: string
  overflowX?: string
  width?: string
  letterSpacing?: string
  fontFamily?: string
  WebkitBackgroundClip?: string
  WebkitTextFillColor?: string
  listStyle?: string
  '@media (max-width: 768px)'?: {
    margin?: string
    padding?: string
    fontSize?: string
  }
}

export interface RendererOptions {
  base?: {
    primaryColor?: string
    textAlign?: string
    lineHeight?: string | number
    fontSize?: string
    themeColor?: string
    padding?: string
    maxWidth?: string
    margin?: string
    wordBreak?: string
    whiteSpace?: string
    color?: string
    fontFamily?: string
  }
  block?: {
    [key: string]: StyleOptions
  }
  inline?: {
    [key: string]: StyleOptions
  }
  dark?: {
    base?: {
      color?: string
    }
    block?: {
      [key: string]: {
        color?: string
        background?: string
        border?: string
        borderLeftColor?: string
        boxShadow?: string
      }
    }
  }
}