import type {
  SceneElement,
  ImageElement,
  TextElement,
} from '../components/canvas'

/**
 * 直接加载图片（不做跨域处理）
 */
function loadImageDirectly(src: string): Promise<HTMLImageElement> {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.crossOrigin = 'anonymous'
    img.onload = () => resolve(img)
    img.onerror = () => reject(new Error(`Failed to load image: ${src}`))
    img.src = src
  })
}

/**
 * 加载图片（通过 fetch 获取 blob，避免跨域污染 canvas）
 * 对于跨域图片，先 fetch 为 blob，再创建 object URL
 */
async function loadImage(src: string): Promise<HTMLImageElement> {
  // 检查是否是 data URL 或 blob URL（这些不需要特殊处理）
  if (src.startsWith('data:') || src.startsWith('blob:')) {
    return loadImageDirectly(src)
  }

  // 检查是否是同源
  try {
    const url = new URL(src, window.location.origin)
    if (url.origin === window.location.origin) {
      // 同源图片直接加载
      return loadImageDirectly(src)
    }
  } catch {
    // URL 解析失败，尝试直接加载
    return loadImageDirectly(src)
  }

  // 跨域图片：通过 fetch 获取 blob
  try {
    const response = await fetch(src, { mode: 'cors' })
    if (!response.ok) {
      throw new Error(`Failed to fetch image: ${response.status}`)
    }
    const blob = await response.blob()
    const blobUrl = URL.createObjectURL(blob)

    try {
      const img = await loadImageDirectly(blobUrl)
      // 注意：这里不立即 revoke，因为 canvas 可能还需要使用
      // 在 exportFrameAsCanvas 完成后会释放
      return img
    } catch (err) {
      URL.revokeObjectURL(blobUrl)
      throw err
    }
  } catch {
    // fetch 失败，回退到直接加载（可能仍会污染 canvas）
    console.warn(
      `[Export] Failed to fetch image via blob, falling back to direct load: ${src}`,
    )
    return loadImageDirectly(src)
  }
}

/**
 * 绘制单行文字
 */
function drawTextLine(
  ctx: CanvasRenderingContext2D,
  line: string,
  boxX: number,
  y: number,
  maxWidth: number,
  textAlign: string,
) {
  let x = boxX
  if (textAlign === 'center') {
    x = boxX + maxWidth / 2
    ctx.textAlign = 'center'
  } else if (textAlign === 'right') {
    x = boxX + maxWidth
    ctx.textAlign = 'right'
  } else {
    ctx.textAlign = 'left'
  }
  ctx.fillText(line, x, y)
}

/**
 * 绘制文本元素并处理换行
 */
function drawTextElement(
  ctx: CanvasRenderingContext2D,
  element: TextElement,
  boxX: number,
  boxY: number,
) {
  const {
    content,
    fontSize = 32,
    fontFamily = 'Inter, sans-serif',
    color = '#000000',
    textAlign = 'left',
    fontWeight = 'normal',
    fontStyle = 'normal',
    width: maxWidth,
  } = element

  ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`
  ctx.fillStyle = color
  ctx.textBaseline = 'top'

  const lineHeight = fontSize * 1.2
  const paragraphs = (content || '').split('\n')
  let currentY = boxY

  for (const paragraph of paragraphs) {
    if (paragraph === '') {
      currentY += lineHeight
      continue
    }

    // 字符级换行，匹配 break-words 逻辑
    const chars = paragraph.split('')
    let currentLine = ''

    for (let n = 0; n < chars.length; n++) {
      const testLine = currentLine + chars[n]
      const metrics = ctx.measureText(testLine)
      const testWidth = metrics.width

      if (testWidth > maxWidth && n > 0 && currentLine !== '') {
        drawTextLine(ctx, currentLine, boxX, currentY, maxWidth, textAlign)
        currentLine = chars[n]
        currentY += lineHeight
      } else {
        currentLine = testLine
      }
    }
    drawTextLine(ctx, currentLine, boxX, currentY, maxWidth, textAlign)
    currentY += lineHeight
  }
}

export function useDownLoadImageGroup(
  selectionBounds: {
    left: number
    top: number
    width: number
    height: number
  } | null,
  elements: Array<SceneElement>,
) {
  const { left = 0, top = 0, width = 0, height = 0 } = selectionBounds ?? {}
  const scale = 2 // 放大倍数，提升图片质量

  const drawCanvas = async () => {
    // 创建 canvas
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    if (!ctx) return
    canvas.width = width * scale
    canvas.height = height * scale
    ctx.scale(scale, scale)

    // 填充白色背景
    ctx.fillStyle = '#ffffff'
    ctx.fillRect(0, 0, width, height)

    // 渲染子元素
    for (const element of elements) {
      if (!element) continue

      const { x, y, width: elWidth, height: elHeight, rotation = 0 } = element
      const boxX = x - left
      const boxY = y - top

      ctx.save()

      // 旋转处理
      if (rotation !== 0) {
        ctx.translate(boxX + elWidth / 2, boxY + elHeight / 2)
        ctx.rotate((rotation * Math.PI) / 180)
        ctx.translate(-(boxX + elWidth / 2), -(boxY + elHeight / 2))
      }

      if (element.type === 'image') {
        const img = await loadImage((element as ImageElement).src)
        ctx.drawImage(img, boxX, boxY, elWidth, elHeight)
      } else if (element.type === 'text') {
        drawTextElement(ctx, element as TextElement, boxX, boxY)
      }

      ctx.restore()
    }
    return canvas
  }

  const downloadCompositeImage = async () => {
    const canvas = await drawCanvas()
    if (!canvas) return
    // 生成图片并下载
    canvas.toBlob(
      blob => {
        if (!blob) return
        const url = URL.createObjectURL(blob)
        const a = document.createElement('a')
        a.href = url
        a.download = `composite-${Date.now()}.jpg`
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
        URL.revokeObjectURL(url)
      },
      'image/jpeg',
      0.95,
    )
  }

  const downloadImage = async (
    src: string,
    fileName: string,
    useCanvas = false,
  ) => {
    if (useCanvas) {
      const img = await loadImage(src)
      // 生成图片并下载
      const canvas = document.createElement('canvas')
      canvas.width = img.width
      canvas.height = img.height
      const ctx = canvas.getContext('2d')
      if (!ctx) return
      ctx.drawImage(img, 0, 0)

      canvas.toBlob(
        blob => {
          if (!blob) return
          const url = URL.createObjectURL(blob)
          const link = document.createElement('a')
          link.href = url
          link.download = fileName || 'image.jpeg'
          document.body.appendChild(link)
          link.click()
          document.body.removeChild(link)
          URL.revokeObjectURL(url)
        },
        'image/jpeg',
        0.95,
      )
    } else {
      // 直接使用a标签下载图片
      const link = document.createElement('a')
      link.href = src
      link.download = fileName || 'image.jpeg'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    }
  }
  return { downloadCompositeImage, downloadImage }
}
