import type { Topic } from '../types/dom'
import type { MindElixirInstance } from '../types'
import { setAttributes } from '../utils'
import { getOffsetLT, isTopic } from '../utils'

const ns = 'http://www.w3.org/2000/svg'
function createSvgDom(height: string, width: string) {
  const svg = document.createElementNS(ns, 'svg')
  setAttributes(svg, {
    version: '1.1',
    xmlns: ns,
    height,
    width,
  })
  return svg
}

function lineHightToPadding(lineHeight: string, fontSize: string) {
  return (parseInt(lineHeight) - parseInt(fontSize)) / 2
}

function generateSvgText(tpc: HTMLElement, tpcStyle: CSSStyleDeclaration, x: number, y: number) {
  const g = document.createElementNS(ns, 'g')
  let content = ''
  if ((tpc as Topic).text) {
    content = (tpc as Topic).text.textContent!
  } else {
    content = tpc.childNodes[0].textContent!
  }
  const lines = content!.split('\n')
  
  // 计算行高和字体大小
  const lineHeight = parseFloat(tpcStyle.lineHeight) || parseFloat(tpcStyle.fontSize) * 1.2
  const fontSize = parseFloat(tpcStyle.fontSize)
  const paddingTop = parseInt(tpcStyle.paddingTop) || 8
  const paddingLeft = parseInt(tpcStyle.paddingLeft) || 8
  
  lines.forEach((line, index) => {
    const text = document.createElementNS(ns, 'text')
    setAttributes(text, {
      x: x + paddingLeft + '',
      y: y + paddingTop + fontSize + (lineHeight * index) + '',
      'text-anchor': 'start',
      'font-family': tpcStyle.fontFamily,
      'font-size': `${tpcStyle.fontSize}`,
      'font-weight': `${tpcStyle.fontWeight}`,
      fill: `${tpcStyle.color}`,
    })
    text.innerHTML = line
    g.appendChild(text)
  })
  return g
}

// 表格转SVG转换器类
class TableToSVGConverter {
  private table: HTMLTableElement
  private cellWidth: number
  private cellHeight: number
  private fontSize: number
  private fontFamily: string

  constructor(table: HTMLTableElement, fontSize: number, fontFamily: string) {
    this.table = table
    this.fontSize = fontSize
    this.fontFamily = fontFamily
    this.cellWidth = 80 // 默认单元格宽度
    this.cellHeight = 30 // 默认单元格高度
  }

  // 分析表格结构，处理rowspan和colspan
  analyzeStructure() {
    const structure: Array<{
      row: number
      col: number
      rowspan: number
      colspan: number
      content: string
      isHeader: boolean
    }> = []

    const rows = this.table.querySelectorAll('tr')
    rows.forEach((row, rowIndex) => {
      const cells = row.querySelectorAll('td, th')
      let colIndex = 0

      cells.forEach(cell => {
        const htmlCell = cell as HTMLTableCellElement
        const rowspan = parseInt(htmlCell.getAttribute('rowspan') || '1')
        const colspan = parseInt(htmlCell.getAttribute('colspan') || '1')
        const content = htmlCell.textContent?.trim() || ''
        const isHeader = htmlCell.tagName.toLowerCase() === 'th'

        structure.push({
          row: rowIndex,
          col: colIndex,
          rowspan,
          colspan,
          content,
          isHeader
        })

        colIndex += colspan
      })
    })

    return structure
  }

  // 计算布局尺寸
  calculateLayout(structure: any[]) {
    const maxCols = Math.max(...structure.map(cell => cell.col + cell.colspan))
    const maxRows = Math.max(...structure.map(cell => cell.row + cell.rowspan))
    
    // 为每列计算最合适的宽度
    const columnWidths: number[] = new Array(maxCols).fill(0)
    
    structure.forEach(cell => {
      // 计算这个单元格内容需要的宽度
      // 中文字符宽度大约是字体大小的1倍，英文是0.6倍
      let contentWidth = 0
      for (const char of cell.content) {
        if (/[\u4e00-\u9fa5]/.test(char)) {
          // 中文字符
          contentWidth += this.fontSize * 1.0
        } else {
          // 英文字符
          contentWidth += this.fontSize * 0.6
        }
      }
      
      // 加上内边距
      contentWidth += 16 // 左右各8px的padding
      
      // 考虑colspan，平均分配宽度
      const avgWidthPerCol = contentWidth / cell.colspan
      
      // 更新这一行涉及的列的最大宽度
      for (let col = cell.col; col < cell.col + cell.colspan; col++) {
        columnWidths[col] = Math.max(columnWidths[col], avgWidthPerCol)
      }
    })
    
    // 设置最小列宽，确保不会太窄
    columnWidths.forEach((width, index) => {
      columnWidths[index] = Math.max(width, 80) // 最小80px
    })
    
    // 计算总宽度
    const totalWidth = columnWidths.reduce((sum, width) => sum + width, 0)
    
    // 计算行高，考虑多行文本
    this.cellHeight = Math.max(35, this.fontSize * 2) // 增加行高
    
    // 为每行计算实际高度（考虑多行文本）
    const rowHeights: number[] = new Array(maxRows).fill(this.cellHeight)
    
    structure.forEach(cell => {
      const lines = cell.content.split('\n').length
      const cellHeight = Math.max(this.cellHeight, lines * this.fontSize * 1.4 + 10)
      
      // 更新这一行涉及的行的高度
      for (let row = cell.row; row < cell.row + cell.rowspan; row++) {
        rowHeights[row] = Math.max(rowHeights[row], cellHeight)
      }
    })
    
    const totalHeight = rowHeights.reduce((sum, height) => sum + height, 0)

    return {
      totalWidth,
      totalHeight,
      cols: maxCols,
      rows: maxRows,
      columnWidths,
      rowHeights
    }
  }

  // 生成SVG元素
  generateSVG(structure: any[], layout: any, x: number, y: number) {
    const svgGroup = document.createElementNS(ns, 'g')
    
    // 绘制表格边框
    const tableRect = document.createElementNS(ns, 'rect')
    setAttributes(tableRect, {
      x: x + '',
      y: y + '',
      width: layout.totalWidth + '',
      height: layout.totalHeight + '',
      fill: 'white',
      stroke: '#ccc',
      'stroke-width': '1'
    })
    svgGroup.appendChild(tableRect)

    // 绘制垂直网格线（使用动态列宽）
    let currentX = x
    for (let i = 0; i < layout.columnWidths.length - 1; i++) {
      currentX += layout.columnWidths[i]
      const line = document.createElementNS(ns, 'line')
      setAttributes(line, {
        x1: currentX + '',
        y1: y + '',
        x2: currentX + '',
        y2: y + layout.totalHeight + '',
        stroke: '#ccc',
        'stroke-width': '1'
      })
      svgGroup.appendChild(line)
    }

    // 绘制水平网格线（使用动态行高）
    let currentY = y
    for (let i = 0; i < layout.rowHeights.length - 1; i++) {
      currentY += layout.rowHeights[i]
      const line = document.createElementNS(ns, 'line')
      setAttributes(line, {
        x1: x + '',
        y1: currentY + '',
        x2: x + layout.totalWidth + '',
        y2: currentY + '',
        stroke: '#ccc',
        'stroke-width': '1'
      })
      svgGroup.appendChild(line)
    }

    // 绘制单元格内容和背景
    structure.forEach(cell => {
      // 计算单元格的实际位置和尺寸
      let cellX = x
      for (let i = 0; i < cell.col; i++) {
        cellX += layout.columnWidths[i]
      }
      
      let cellY = y
      for (let i = 0; i < cell.row; i++) {
        cellY += layout.rowHeights[i]
      }
      
      // 计算单元格宽度（考虑colspan）
      let cellWidth = 0
      for (let i = cell.col; i < cell.col + cell.colspan; i++) {
        cellWidth += layout.columnWidths[i]
      }
      
      // 计算单元格高度（考虑rowspan）
      let cellHeight = 0
      for (let i = cell.row; i < cell.row + cell.rowspan; i++) {
        cellHeight += layout.rowHeights[i]
      }

      // 绘制单元格背景
      if (cell.isHeader) {
        const bgRect = document.createElementNS(ns, 'rect')
        setAttributes(bgRect, {
          x: cellX + '',
          y: cellY + '',
          width: cellWidth + '',
          height: cellHeight + '',
          fill: '#f5f5f5',
          stroke: 'none'
        })
        svgGroup.appendChild(bgRect)
      }

      // 绘制文本内容
      if (cell.content) {
        const text = document.createElementNS(ns, 'text')
        setAttributes(text, {
          x: cellX + cellWidth / 2 + '',
          y: cellY + cellHeight / 2 + this.fontSize / 3 + '',
          'text-anchor': 'middle',
          'dominant-baseline': 'central',
          'font-family': this.fontFamily,
          'font-size': this.fontSize + '',
          'font-weight': cell.isHeader ? 'bold' : 'normal',
          fill: '#333'
        })
        
        // 处理多行文本
        const lines = cell.content.split('\n')
        if (lines.length === 1) {
          text.textContent = cell.content
        } else {
          lines.forEach((line: string, index: number) => {
            const tspan = document.createElementNS(ns, 'tspan')
            setAttributes(tspan, {
              x: cellX + cellWidth / 2 + '',
              dy: index === 0 ? '0' : '1.2em'
            })
            tspan.textContent = line
            text.appendChild(tspan)
          })
        }
        
        svgGroup.appendChild(text)
      }
    })

    return svgGroup
  }

  // 转换表格为SVG
  convert(x: number, y: number) {
    const structure = this.analyzeStructure()
    const layout = this.calculateLayout(structure)
    return this.generateSVG(structure, layout, x, y)
  }
}

// 清理HTML内容，修复SVG解析错误
function cleanHtmlForSvg(html: string): string {
  if (!html) return html
  
  // 修复表格中的<br>标签问题 - 将<td>内的<br>替换为空格
  let cleanedHtml = html.replace(/<td[^>]*>([^<]*)<br\s*\/?>([^<]*)<\/td>/gi, (match, before, after) => {
    return `<td>${before} ${after}</td>`
  })
  
  // 修复<th>中的<br>标签问题
  cleanedHtml = cleanedHtml.replace(/<th[^>]*>([^<]*)<br\s*\/?>([^<]*)<\/th>/gi, (match, before, after) => {
    return `<th>${before} ${after}</th>`
  })
  
  // 移除其他可能导致SVG解析错误的标签
  cleanedHtml = cleanedHtml.replace(/<br\s*\/?>/gi, ' ')
  
  // 确保所有标签都正确闭合
  cleanedHtml = cleanedHtml.replace(/<([^>]+)>/g, (match, tagContent) => {
    // 检查是否是自闭合标签
    const selfClosingTags = ['br', 'hr', 'img', 'input', 'meta', 'link']
    const tagName = tagContent.split(' ')[0].toLowerCase()
    
    if (selfClosingTags.includes(tagName)) {
      return `<${tagContent} />`
    }
    return match
  })
  
  return cleanedHtml
}

function generateSvgTextUsingForeignObject(tpc: HTMLElement, tpcStyle: CSSStyleDeclaration, x: number, y: number) {
  const g = document.createElementNS(ns, 'g')
  
  // 检查内容来源
  const tpcWithNodeObj = tpc as Topic
  let htmlContent = ''
  
  // 优先使用dangerouslySetInnerHTML，其次使用text.innerHTML
  if (tpcWithNodeObj.nodeObj && tpcWithNodeObj.nodeObj.dangerouslySetInnerHTML) {
    htmlContent = tpcWithNodeObj.nodeObj.dangerouslySetInnerHTML
    console.log('🔍 使用dangerouslySetInnerHTML内容:', htmlContent.substring(0, 200))
  } else if (tpcWithNodeObj.text && tpcWithNodeObj.text.innerHTML) {
    htmlContent = tpcWithNodeObj.text.innerHTML
    console.log('🔍 使用text.innerHTML内容:', htmlContent.substring(0, 200))
  }
  
  const hasHTMLContent = htmlContent && htmlContent !== tpc.textContent
  const hasTableContent = htmlContent && htmlContent.includes('<table')
  
  console.log('🔍 HTML内容分析:', {
    hasHTMLContent,
    hasTableContent,
    contentLength: htmlContent.length
  })
  
  // 如果包含表格，使用新的SVG原生转换器
  if (hasTableContent) {
    console.log('🔄 检测到表格内容，使用SVG原生转换器')
    
    // 创建一个临时DOM元素来解析表格
    const tempDiv = document.createElement('div')
    tempDiv.innerHTML = cleanHtmlForSvg(htmlContent)
    const table = tempDiv.querySelector('table') as HTMLTableElement
    
    if (table) {
      const fontSize = parseFloat(tpcStyle.fontSize) || 14
      const fontFamily = tpcStyle.fontFamily || 'Arial, sans-serif'
      
      const converter = new TableToSVGConverter(table, fontSize, fontFamily)
      const tableSVG = converter.convert(x, y)
      
      g.appendChild(tableSVG)
      console.log('✅ 表格已转换为SVG原生元素')
      return g
    }
  }
  
  if (hasHTMLContent || hasTableContent) {
    // 清理HTML内容，修复SVG解析错误
    const cleanedHtml = cleanHtmlForSvg(htmlContent)
    console.log('🔍 清理后的HTML内容:', cleanedHtml.substring(0, 200))
    
    // 对于HTML内容，使用foreignObject来正确渲染
    const foreignObject = document.createElementNS(ns, 'foreignObject')
    
    // 获取节点的实际尺寸，并大幅增加高度以防止图片压线
    const nodeWidth = parseInt(tpcStyle.width) || 200
    const originalHeight = parseInt(tpcStyle.height) || 100
    const nodeHeight = originalHeight + 50 // 大幅增加50px高度给图片留出空间
    
    setAttributes(foreignObject, {
      x: x + '',
      y: y + '',
      width: nodeWidth + 'px',
      height: nodeHeight + 'px',
    })
    
    // 创建div容器来包含HTML内容
    const div = document.createElement('div')
    div.innerHTML = cleanedHtml
    
    // 应用样式，确保与思维导图显示一致，大幅增加底部padding防止图片压线
    const paddingTop = parseInt(tpcStyle.paddingTop) || 8
    const paddingBottom = Math.max(parseInt(tpcStyle.paddingBottom) || 8, 35) // 大幅增加底部padding到35px
    const paddingLeft = parseInt(tpcStyle.paddingLeft) || 8
    const paddingRight = parseInt(tpcStyle.paddingRight) || 8
    
    div.style.cssText = `
      width: 100%;
      height: auto;
      min-height: 100%;
      font-family: ${tpcStyle.fontFamily};
      font-size: ${tpcStyle.fontSize};
      color: ${tpcStyle.color};
      background: transparent;
      padding: ${paddingTop}px ${paddingRight}px ${paddingBottom}px ${paddingLeft}px;
      box-sizing: border-box;
      overflow: visible;
      text-align: center;
      line-height: 1.4;
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      align-items: center;
      position: relative;
    `
    
    // 为表格添加样式
    const tables = div.querySelectorAll('table')
    tables.forEach(table => {
      const htmlTable = table as HTMLTableElement
      htmlTable.style.cssText = `
        width: 100%;
        border-collapse: collapse;
        font-size: ${tpcStyle.fontSize};
        font-family: ${tpcStyle.fontFamily};
        margin: 0 auto;
        border: 1px solid #ccc;
      `
      
      // 为表格单元格添加样式
      const cells = table.querySelectorAll('td, th')
      cells.forEach(cell => {
        const htmlCell = cell as HTMLElement
        htmlCell.style.cssText = `
          border: 1px solid #ccc;
          padding: 4px 8px;
          text-align: center;
          vertical-align: top;
          font-size: ${parseFloat(tpcStyle.fontSize) * 0.9}px;
          background: white;
        `
      })
    })
    
    // 优化列表样式，减少底部空白
    const lists = div.querySelectorAll('ul, ol')
    lists.forEach(list => {
      const htmlList = list as HTMLElement
      htmlList.style.cssText = `
        margin: 2px 0 4px 0;
        padding-left: 20px;
        text-align: left;
      `
    })
    
    const listItems = div.querySelectorAll('li')
    listItems.forEach(item => {
      const htmlItem = item as HTMLElement
      htmlItem.style.cssText = `
        margin: 1px 0;
        line-height: 1.2;
        padding: 0;
      `
    })
    
    // 为图片元素添加特殊样式处理，彻底解决图片压线问题
    const images = div.querySelectorAll('img')
    images.forEach((img, index) => {
      const htmlImg = img as HTMLImageElement
      
      // 更大的图片尺寸，减少图片和文字距离
      const availableWidth = nodeWidth - paddingLeft - paddingRight - 5 // 进一步减少边距
      const availableHeight = Math.floor(nodeHeight * 0.7) // 增加到70%高度
      
      htmlImg.style.cssText = `
        max-width: ${availableWidth}px !important;
        max-height: ${availableHeight}px !important;
        width: auto !important;
        height: auto !important;
        display: block !important;
        margin: 8px auto 20px auto !important;
        border-radius: 4px;
        object-fit: contain !important;
        flex-shrink: 0 !important;
        box-sizing: border-box !important;
        position: relative !important;
        top: 0 !important;
        left: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
      `
      
      console.log(`🖼️ 图片 ${index + 1} 强制尺寸控制:`, {
        nodeWidth,
        nodeHeight,
        availableWidth,
        availableHeight,
        paddingLeft,
        paddingRight,
        bottomMargin: '20px'
      })
    })
    
    foreignObject.appendChild(div)
    g.appendChild(foreignObject)
    console.log('✅ 使用foreignObject渲染HTML内容')
  } else {
    // 对于纯文本内容，使用原生SVG文本渲染
    return generateSvgText(tpc, tpcStyle, x, y)
  }
  
  return g
}

function createElBox(mei: MindElixirInstance, tpc: Topic) {
  const tpcStyle = getComputedStyle(tpc)
  const { offsetLeft: x, offsetTop: y } = getOffsetLT(mei.nodes, tpc)

  // 检查是否有HTML内容或节点图片，如果有则增加高度
  const tpcWithNodeObj = tpc as Topic
  const hasHTMLContent = tpcWithNodeObj.nodeObj && tpcWithNodeObj.nodeObj.dangerouslySetInnerHTML
  const hasImages = hasHTMLContent && tpcWithNodeObj.nodeObj.dangerouslySetInnerHTML?.includes('<img')
  const hasNodeImage = tpcWithNodeObj.nodeObj && tpcWithNodeObj.nodeObj.image
  
  const originalHeight = parseInt(tpcStyle.height) || 100
  const adjustedHeight = (hasImages || hasNodeImage) ? originalHeight + 50 : originalHeight

  const bg = document.createElementNS(ns, 'rect')
  setAttributes(bg, {
    x: x + '',
    y: y + '',
    rx: tpcStyle.borderRadius,
    ry: tpcStyle.borderRadius,
    width: tpcStyle.width,
    height: adjustedHeight + 'px',
    fill: tpcStyle.backgroundColor,
    stroke: tpcStyle.borderColor,
    'stroke-width': tpcStyle.borderWidth,
  })
  return bg
}
function convertDivToSvg(mei: MindElixirInstance, tpc: HTMLElement, useForeignObject = false) {
  const tpcStyle = getComputedStyle(tpc)
  const { offsetLeft: x, offsetTop: y } = getOffsetLT(mei.nodes, tpc)

  // 检查是否有HTML内容或节点图片，如果有则增加高度
  const tpcWithNodeObj2 = tpc as Topic
  const hasHTMLContent2 = tpcWithNodeObj2.nodeObj && tpcWithNodeObj2.nodeObj.dangerouslySetInnerHTML
  const hasImages2 = hasHTMLContent2 && tpcWithNodeObj2.nodeObj.dangerouslySetInnerHTML?.includes('<img')
  const hasNodeImage2 = tpcWithNodeObj2.nodeObj && tpcWithNodeObj2.nodeObj.image
  
  const originalHeight2 = parseInt(tpcStyle.height) || 100
  const adjustedHeight2 = (hasImages2 || hasNodeImage2) ? originalHeight2 + 50 : originalHeight2

  const bg = document.createElementNS(ns, 'rect')
  setAttributes(bg, {
    x: x + '',
    y: y + '',
    rx: tpcStyle.borderRadius,
    ry: tpcStyle.borderRadius,
    width: tpcStyle.width,
    height: adjustedHeight2 + 'px',
    fill: tpcStyle.backgroundColor,
    stroke: tpcStyle.borderColor,
    'stroke-width': tpcStyle.borderWidth,
  })
  const g = document.createElementNS(ns, 'g')
  g.appendChild(bg)
  
  let text: SVGGElement | null = null
  
  // 检查是否有dangerouslySetInnerHTML内容
  const tpcWithNodeObj3 = tpc as Topic
  if (tpcWithNodeObj3.nodeObj && tpcWithNodeObj3.nodeObj.dangerouslySetInnerHTML) {
    console.log('🔍 处理dangerouslySetInnerHTML内容:', tpcWithNodeObj3.nodeObj.dangerouslySetInnerHTML.substring(0, 200))
    // 对于dangerouslySetInnerHTML，使用ForeignObject
    text = generateSvgTextUsingForeignObject(tpc, tpcStyle, x, y)
  } else if (useForeignObject) {
    // 对于其他HTML内容，也使用ForeignObject
    text = generateSvgTextUsingForeignObject(tpc, tpcStyle, x, y)
  } else {
    // 对于普通文本内容
    text = generateSvgText(tpc, tpcStyle, x, y)
  }
  
  if (text) {
    g.appendChild(text)
  }
  
  return g
}

function convertAToSvg(mei: MindElixirInstance, a: HTMLAnchorElement) {
  const aStyle = getComputedStyle(a)
  const { offsetLeft: x, offsetTop: y } = getOffsetLT(mei.nodes, a)
  const svgA = document.createElementNS(ns, 'a')
  const text = document.createElementNS(ns, 'text')
  setAttributes(text, {
    x: x + '',
    y: y + parseInt(aStyle.fontSize) + '',
    'text-anchor': 'start',
    'font-family': aStyle.fontFamily,
    'font-size': `${aStyle.fontSize}`,
    'font-weight': `${aStyle.fontWeight}`,
    fill: `${aStyle.color}`,
  })
  text.innerHTML = a.textContent!
  svgA.appendChild(text)
  svgA.setAttribute('href', a.href)
  return svgA
}

async function convertNodeImageToSvg(mei: MindElixirInstance, tpc: Topic): Promise<SVGImageElement | null> {
  const tpcStyle = getComputedStyle(tpc)
  const { offsetLeft: x, offsetTop: y } = getOffsetLT(mei.nodes, tpc)
  
  if (!tpc.nodeObj.image) {
    return null
  }
  
  const imageData = tpc.nodeObj.image
  const svgI = document.createElementNS(ns, 'image')
  
  console.log('🖼️ 处理节点图片:', imageData)
  
  // 计算图片位置，为文字预留空间，限制图片尺寸防止压线
  const nodeWidth = parseInt(tpcStyle.width)
  const nodeHeight = parseInt(tpcStyle.height)
  const maxImgWidth = Math.min(nodeWidth - 10, 300) // 进一步减少边距，增加最大宽度
  const maxImgHeight = Math.min(nodeHeight * 0.6, 150) // 增加最大高度为节点的60%
  const imgWidth = Math.min(imageData.width || 200, maxImgWidth)
  const imgHeight = Math.min(imageData.height || 150, maxImgHeight)
  
  // 计算文字内容的高度
  let textHeight = 0
  if (tpc.text && tpc.text.textContent) {
    const textContent = tpc.text.textContent.trim()
    if (textContent) {
      // 估算文字高度：行数 * 行高
      const lines = textContent.split('\n').length
      const lineHeight = parseFloat(tpcStyle.lineHeight) || parseFloat(tpcStyle.fontSize) * 1.2
      const fontSize = parseFloat(tpcStyle.fontSize)
      const paddingTop = parseInt(tpcStyle.paddingTop) || 8
      const paddingBottom = parseInt(tpcStyle.paddingBottom) || 8
      
      textHeight = lines * lineHeight + paddingTop + paddingBottom
      console.log('📝 文字高度计算:', { lines, lineHeight, fontSize, textHeight })
    }
  }
  
  // 图片位置：水平居中，垂直位置考虑文字高度，大幅增加底部间距
  const imgX = x + (nodeWidth - imgWidth) / 2
  const imgY = y + textHeight + 20 // 减少底部间距到20px，让图片和文字更接近
  
  try {
    // 尝试将图片转换为base64
    const base64Url = await imageToBase64(imageData.url)
    setAttributes(svgI, {
      x: imgX + '',
      y: imgY + '',
      width: imgWidth + '',
      height: imgHeight + '',
      href: base64Url,
    })
    console.log('✅ 成功导出节点图片')
  } catch (error) {
    console.warn('⚠️ 图片转base64失败，使用原始URL:', error)
    setAttributes(svgI, {
      x: imgX + '',
      y: imgY + '',
      width: imgWidth + '',
      height: imgHeight + '',
      href: imageData.url,
    })
  }
  
  return svgI
}

async function convertImgToSvg(mei: MindElixirInstance, a: HTMLImageElement): Promise<SVGImageElement> {
  const aStyle = getComputedStyle(a)
  const { offsetLeft: x, offsetTop: y } = getOffsetLT(mei.nodes, a)
  const svgI = document.createElementNS(ns, 'image')
  
  // Use imageProxy function if provided, otherwise use original URL
  const imageUrl = mei.imageProxy ? mei.imageProxy(a.src) : a.src
  
  // 获取图片的实际显示尺寸，确保与思维导图中的显示一致
  const actualWidth = Math.min(parseInt(aStyle.width) || 300, 300)
  const actualHeight = Math.min(parseInt(aStyle.height) || 200, 200)
  
  console.log('🖼️ 图片导出尺寸:', {
    computedWidth: aStyle.width,
    computedHeight: aStyle.height,
    actualWidth,
    actualHeight,
    imageUrl: imageUrl.substring(0, 50)
  })
  
  // 尝试将图片转换为base64格式以确保导出时能正确显示
  try {
    const base64Url = await imageToBase64(imageUrl)
    setAttributes(svgI, {
      x: x + '',
      y: y + '',
      width: actualWidth + '',
      height: actualHeight + '',
      href: base64Url,
    })
  } catch (error) {
    console.warn('Failed to convert image to base64, using original URL:', error)
    setAttributes(svgI, {
      x: x + '',
      y: y + '',
      width: actualWidth + '',
      height: actualHeight + '',
      href: imageUrl,
    })
  }
  
  return svgI
}

// 将图片URL转换为base64格式
function imageToBase64(url: string): Promise<string> {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.crossOrigin = 'anonymous'
    
    img.onload = () => {
      try {
        const canvas = document.createElement('canvas')
        canvas.width = img.width
        canvas.height = img.height
        const ctx = canvas.getContext('2d')
        
        if (!ctx) {
          reject(new Error('Failed to get canvas context'))
          return
        }
        
        ctx.drawImage(img, 0, 0)
        const base64 = canvas.toDataURL('image/png')
        resolve(base64)
      } catch (error) {
        reject(error)
      }
    }
    
    img.onerror = () => {
      reject(new Error('Failed to load image'))
    }
    
    img.src = url
  })
}

const padding = 100

const head = `<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">`

const generateSvg = async (mei: MindElixirInstance, noForeignObject = false) => {
  const mapDiv = mei.nodes
  const height = mapDiv.offsetHeight + padding * 2
  const width = mapDiv.offsetWidth + padding * 2
  const svg = createSvgDom(height + 'px', width + 'px')
  const g = document.createElementNS(ns, 'svg')
  const bgColor = document.createElementNS(ns, 'rect')
  setAttributes(bgColor, {
    x: '0',
    y: '0',
    width: `${width}`,
    height: `${height}`,
    fill: mei.theme.cssVar['--bgcolor'] as string,
  })
  svg.appendChild(bgColor)
  mapDiv.querySelectorAll('.subLines').forEach(item => {
    const clone = item.cloneNode(true) as SVGSVGElement
    const { offsetLeft, offsetTop } = getOffsetLT(mapDiv, item.parentElement as HTMLElement)
    clone.setAttribute('x', `${offsetLeft}`)
    clone.setAttribute('y', `${offsetTop}`)
    g.appendChild(clone)
  })

  const mainLine = mapDiv.querySelector('.lines')?.cloneNode(true)
  mainLine && g.appendChild(mainLine)
  const topiclinks = mapDiv.querySelector('.topiclinks')?.cloneNode(true)
  topiclinks && g.appendChild(topiclinks)
  const summaries = mapDiv.querySelector('.summary')?.cloneNode(true)
  summaries && g.appendChild(summaries)

  // 处理所有节点
  const nodePromises = Array.from(mapDiv.querySelectorAll<Topic>('me-tpc')).map(async (tpc) => {
    // 首先创建节点背景
    g.appendChild(createElBox(mei, tpc))
    
    // 检查节点内容类型
    const hasDangerouslySetInnerHTML = tpc.nodeObj.dangerouslySetInnerHTML
    const hasHTMLContent = !!(tpc.text && tpc.text.innerHTML && tpc.text.innerHTML !== tpc.text.textContent)
    const hasImage = tpc.nodeObj.image
    
    console.log('🔍 节点内容分析:', {
      hasDangerouslySetInnerHTML,
      hasHTMLContent,
      hasImage,
      innerHTML: tpc.text?.innerHTML?.substring(0, 100),
      textContent: tpc.text?.textContent?.substring(0, 100)
    })
    
    // 处理不同类型的节点内容
    if (hasDangerouslySetInnerHTML || hasHTMLContent) {
      // 对于HTML内容（表格等），使用ForeignObject
      console.log('✅ 使用ForeignObject渲染HTML内容')
      g.appendChild(convertDivToSvg(mei, tpc, noForeignObject ? false : true))
    } else if (!hasImage) {
      // 对于没有图片的普通文本内容
      g.appendChild(convertDivToSvg(mei, tpc, false))
    } else {
      // 对于有图片的节点，只渲染文字部分（不包含图片）
      console.log('📝 渲染有图片节点的文字内容')
      g.appendChild(convertDivToSvg(mei, tpc, false))
    }
    
    // 如果有图片，单独处理图片
    if (hasImage) {
      console.log('🖼️ 处理节点图片:', tpc.nodeObj.image)
      try {
        const imageSvg = await convertNodeImageToSvg(mei, tpc)
        if (imageSvg) {
          g.appendChild(imageSvg)
        }
      } catch (error) {
        console.error('❌ 图片导出失败:', error)
      }
    }
  })
  
  // 等待所有节点处理完成
  await Promise.all(nodePromises)
  mapDiv.querySelectorAll('.tags > span').forEach(tag => {
    g.appendChild(convertDivToSvg(mei, tag as HTMLElement))
  })
  mapDiv.querySelectorAll('.icons > span').forEach(icon => {
    g.appendChild(convertDivToSvg(mei, icon as HTMLElement))
  })
  mapDiv.querySelectorAll('.hyper-link').forEach(hl => {
    g.appendChild(convertAToSvg(mei, hl as HTMLAnchorElement))
  })
  // 处理图片元素 - 只处理不在节点内的独立图片
  const allImages = Array.from(mapDiv.querySelectorAll('img'))
  console.log('🔍 发现的所有图片元素:', allImages.length)
  
  const imgPromises = allImages.map(async (img, index) => {
    // 检查图片是否在节点内
    const parentNode = img.closest('me-tpc')
    const isInForeignObject = img.closest('foreignObject')
    
    console.log(`🖼️ 处理图片 ${index + 1}:`, {
      isInNode: !!parentNode,
      isInForeignObject: !!isInForeignObject,
      src: img.src.substring(0, 50)
    })
    
    // 如果图片在节点内，跳过独立处理（节点已经包含了完整内容）
    if (parentNode || isInForeignObject) {
      console.log('⏭️ 跳过节点内图片')
      return null
    }
    
    // 只处理独立的图片元素
    console.log('✅ 处理独立图片')
    return await convertImgToSvg(mei, img)
  })
  
  const imgElements = await Promise.all(imgPromises)
  const validImgElements = imgElements.filter(imgEl => imgEl !== null)
  console.log('📊 有效图片元素数量:', validImgElements.length)
  
  validImgElements.forEach(imgEl => {
    if (imgEl) {
      g.appendChild(imgEl)
    }
  })
  setAttributes(g, {
    x: padding + '',
    y: padding + '',
    overflow: 'visible',
  })
  svg.appendChild(g)
  return svg
}

const generateSvgStr = (svgEl: SVGSVGElement, injectCss?: string) => {
  if (injectCss) svgEl.insertAdjacentHTML('afterbegin', '<style>' + injectCss + '</style>')
  return head + svgEl.outerHTML
}

function blobToUrl(blob: Blob): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = evt => {
      resolve(evt.target!.result as string)
    }
    reader.onerror = err => {
      reject(err)
    }
    reader.readAsDataURL(blob)
  })
}

export const exportSvg = async function (this: MindElixirInstance, noForeignObject = false, injectCss?: string) {
  const svgEl = await generateSvg(this, noForeignObject)
  const svgString = generateSvgStr(svgEl, injectCss)
  const blob = new Blob([svgString], { type: 'image/svg+xml' })
  return blob
}

export const exportPng = async function (this: MindElixirInstance, noForeignObject = false, injectCss?: string): Promise<Blob | null> {
  const blob = await this.exportSvg(noForeignObject, injectCss)
  // use base64 to bypass canvas taint
  const url = await blobToUrl(blob)
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.setAttribute('crossOrigin', 'anonymous')
    
    // 增加超时处理
    const timeout = setTimeout(() => {
      reject(new Error('Image loading timeout'))
    }, 10000)
    
    img.onload = () => {
      clearTimeout(timeout)
      try {
        const canvas = document.createElement('canvas')
        canvas.width = img.width
        canvas.height = img.height
        const ctx = canvas.getContext('2d')!
        
        // 设置白色背景
        ctx.fillStyle = '#ffffff'
        ctx.fillRect(0, 0, canvas.width, canvas.height)
        
        ctx.drawImage(img, 0, 0)
        canvas.toBlob(resolve, 'image/png', 1)
      } catch (error) {
        reject(error)
      }
    }
    
    img.onerror = (error) => {
      clearTimeout(timeout)
      console.error('Image loading failed:', error)
      reject(error)
    }
    
    img.src = url
  })
}
