/**
 * html-to-image 核心工具模块
 * 提供通用的样式处理和图片生成功能，供打印和PDF导出复用
 */
import { toPng, toJpeg } from 'html-to-image'

/**
 * 样式备份和恢复管理器
 */
export class StyleManager {
  constructor (element) {
    this.element = element
    this.styleBackups = []
    this.originalStyle = null
    this.originalScrollTop = 0
    this.originalScrollLeft = 0
  }

  /**
   * 备份并调整元素样式以适应打印/导出
   */
  backup () {
    this.originalStyle = this.element.style.cssText
    this.originalScrollTop = this.element.scrollTop
    this.originalScrollLeft = this.element.scrollLeft

    const allElements = this.element.querySelectorAll('*')
    allElements.forEach(el => {
      const computedStyle = window.getComputedStyle(el)
      const hasOverflow = computedStyle.overflow !== 'visible' ||
        computedStyle.overflowY !== 'visible' ||
        computedStyle.overflowX !== 'visible'
      const hasFixedHeight = el.style.height && el.style.height.includes('calc')

      if (hasOverflow || hasFixedHeight) {
        this.styleBackups.push({
          element: el,
          overflow: el.style.overflow,
          overflowX: el.style.overflowX,
          overflowY: el.style.overflowY,
          height: el.style.height,
          maxHeight: el.style.maxHeight,
          minHeight: el.style.minHeight
        })

        el.style.overflow = 'visible'
        el.style.overflowX = 'visible'
        el.style.overflowY = 'visible'
        if (hasFixedHeight) {
          el.style.height = 'auto'
          el.style.maxHeight = 'none'
          el.style.minHeight = '0'
        }
      }
    })

    this.element.style.overflow = 'visible'
    this.element.style.overflowX = 'visible'
    this.element.style.overflowY = 'visible'
    this.element.style.height = 'auto'
    this.element.style.maxHeight = 'none'
    this.element.style.border = 'none'
    this.element.style.outline = 'none'
    this.element.style.boxShadow = 'none'
  }

  restore () {
    try {
      this.styleBackups.forEach(backup => {
        try {
          backup.element.style.overflow = backup.overflow
          backup.element.style.overflowX = backup.overflowX
          backup.element.style.overflowY = backup.overflowY
          backup.element.style.height = backup.height
          backup.element.style.maxHeight = backup.maxHeight
          backup.element.style.minHeight = backup.minHeight
        } catch (e) {
          console.warn('恢复子元素样式失败:', e)
        }
      })

      this.element.style.cssText = this.originalStyle
      this.element.scrollTop = this.originalScrollTop
      this.element.scrollLeft = this.originalScrollLeft
    } catch (e) {
      console.error('恢复样式失败:', e)
    }
  }
}

/**
 * 生成元素的图片数据URL
 */
export const generateImage = async (element, options = {}) => {
  const {
    format = 'png',
    quality = 0.95,
    pixelRatio = 2,
    backgroundColor = '#ffffff'
  } = options

  const commonOptions = {
    cacheBust: true,
    pixelRatio,
    backgroundColor,
    filter: (node) => {
      if (node.classList) {
        return !node.classList.contains('ant-drawer-mask') &&
          !node.classList.contains('no-print')
      }
      return true
    }
  }

  if (format === 'jpeg') {
    return await toJpeg(element, { ...commonOptions, quality })
  } else {
    return await toPng(element, commonOptions)
  }
}

/**
 * 处理元素导出的完整流程
 */
export const processElement = async (elementId, options = {}) => {
  const element = document.getElementById(elementId)

  if (!element) {
    const error = new Error(`未找到ID为"${elementId}"的元素`)
    console.error(error.message)
    return Promise.reject(error)
  }

  let restoreFunction = null
  const styleManager = new StyleManager(element)

  try {
    if (options.beforeProcess && typeof options.beforeProcess === 'function') {
      restoreFunction = await options.beforeProcess(element)
    }

    styleManager.backup()
    await new Promise(resolve => setTimeout(resolve, 100))
    const dataUrl = await generateImage(element, options)
    styleManager.restore()

    if (restoreFunction && typeof restoreFunction === 'function') {
      restoreFunction()
    }

    if (options.afterProcess && typeof options.afterProcess === 'function') {
      await options.afterProcess()
    }

    return dataUrl
  } catch (error) {
    styleManager.restore()
    if (restoreFunction && typeof restoreFunction === 'function') {
      restoreFunction()
    }
    console.error('元素处理失败:', error)
    return Promise.reject(error)
  }
}
