<template>
  <view class="poster-page">
    <view class="preview-container" v-if="posterUrl">
      <image :src="posterUrl" mode="widthFix" class="poster-img"></image>
      <button class="save-btn" @click="saveToAlbum">保存到相册</button>
    </view>
    <button class="generate-btn" @click="generatePoster" v-if="!posterUrl">生成海报</button>
    <canvas
      id="posterCanvas"
      type="2d"
      :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
      class="canvas-hidden"
    ></canvas>
  </view>
</template>

<script setup>
import { ref, getCurrentInstance } from 'vue'
import { onReady } from '@dcloudio/uni-app'

// 基础变量（不变）
const canvasWidth = ref(375)
const canvasHeight = ref(667)
const posterUrl = ref('')
let canvasNode = null
let ctx = null
const instance = getCurrentInstance()

// 海报配置（不变）
const posterConfig = {
  bgImage: 'https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/1/677c4a5ae43a45eb98c0ae1a6d242021.png',
  title: { text: '限时优惠活动', x: 20, y: 40, fontSize: 24, color: '#fff', fontWeight: 'bold' },
  desc: { text: '全场商品满200减50，限时3天', x: 20, y: 80, fontSize: 16, color: '#fff' },
  mainImage: { url: 'https://img.yzcdn.cn/vant/apple-1.jpg', x: 20, y: 120, width: 335, height: 335, radius: 10 },
  qrcode: { url: 'https://czg-oss.oss-cn-hangzhou.aliyuncs.com/catering/store/HQ200龙虾仔.JPG', x: 265, y: 500, width: 90, height: 90 },
  footerText: { text: '扫码立即参与活动', x: 20, y: 550, fontSize: 14, color: '#333' }
}

// 初始化 Canvas（不变）
onReady(() => {
  const query = uni.createSelectorQuery().in(instance)
  query
    .select('#posterCanvas')
    .fields({ node: true, size: true })
    .exec((res) => {
      if (!res[0] || !res[0].node) {
        console.error('未找到 Canvas 节点')
        uni.showToast({ title: 'Canvas节点初始化失败', icon: 'none' })
        return
      }
      canvasNode = res[0].node
      canvasNode.width = canvasWidth.value
      canvasNode.height = canvasHeight.value
      ctx = canvasNode.getContext('2d')
      if (!ctx) {
        console.error('获取 2D 上下文失败')
        uni.showToast({ title: 'Canvas上下文初始化失败', icon: 'none' })
      }
    })
})

// 绘制背景（依赖修复后的 drawImage）
const drawBackground = () => {
  return new Promise((resolve, reject) => {
    if (!posterConfig.bgImage) return reject('无背景图')
    drawImage({
      url: posterConfig.bgImage,
      x: 0,
      y: 0,
      width: canvasWidth.value,
      height: canvasHeight.value
    }).then(resolve).catch(reject)
  })
}

// 绘制文字（不变）
const drawText = (options) => {
  const { text, x, y, fontSize, color, fontWeight = 'normal', fontFamily = 'sans-serif' } = options
  ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`
  ctx.fillStyle = color
  ctx.fillText(text, x, y)
}

// 绘制圆角矩形（不变）
const drawRoundRect = (x, y, width, height, radius) => {
  ctx.beginPath()
  ctx.moveTo(x + radius, y)
  ctx.arcTo(x + width, y, x + width, y + height, radius)
  ctx.arcTo(x + width, y + height, x, y + height, radius)
  ctx.arcTo(x, y + height, x, y, radius)
  ctx.arcTo(x, y, x + width, y, radius)
  ctx.closePath()
}

// ---------------------- 核心修复：drawImage 方法（无需 Image 实例） ----------------------
const drawImage = (options) => {
  return new Promise((resolve, reject) => {
    const { url, x, y, width, height, radius = 0 } = options
    if (!url) return reject('图片路径为空')
    if (width <= 0 || height <= 0) return reject(`图片尺寸无效：${width}x${height}`)
    // 关键：确保 canvasNode 已初始化（否则无法创建图片对象）
    if (!canvasNode) return reject('Canvas 节点未初始化，无法创建图片对象')

    // 1. 获取图片临时路径（不变）
    uni.getImageInfo({
      src: url,
      success: (imgInfo) => {
        if (imgInfo.width <= 0 || imgInfo.height <= 0) {
          return reject(`无效图片：${url}`)
        }

        // 2. 关键修复：用 Canvas 节点的 createImage() 方法创建图片对象
        // 这是微信小程序 Canvas 2D 节点原生支持的方法，类型完全匹配
        const image = canvasNode.createImage()

        // 3. 监听图片加载完成（接口与标准 Image 一致）
        image.onload = () => {
          try {
            if (radius > 0) {
              ctx.save()
              drawRoundRect(x, y, width, height, radius)
              ctx.clip()
            }

            // 4. 绘制图片：传入 Canvas 节点创建的图片实例（类型匹配）
            ctx.drawImage(image, x, y, width, height)

            if (radius > 0) ctx.restore()
            resolve()
          } catch (drawErr) {
            reject(`绘制图片失败：${drawErr.message}`)
          }
        }

        // 监听加载失败
        image.onerror = (err) => {
          reject(`图片加载失败：${err.message || '未知错误'}`)
        }

        // 5. 赋值临时路径，触发加载
        image.src = imgInfo.path
      },
      fail: (err) => {
        reject(`获取图片信息失败：${err.errMsg}（路径：${url}）`)
      }
    })
  })
}

// 生成海报（不变）
const generatePoster = async () => {
  try {
    if (!canvasNode || !ctx) throw new Error('Canvas 未初始化完成')
    ctx.clearRect(0, 0, canvasWidth.value, canvasHeight.value)

    // 绘制背景（失败则用纯色兜底）
    await drawBackground().catch(() => {
      ctx.fillStyle = '#f5f5f5'
      ctx.fillRect(0, 0, canvasWidth.value, canvasHeight.value)
    })

    // 绘制文字
    drawText(posterConfig.title)
    drawText(posterConfig.desc)
    drawText(posterConfig.footerText)

    // 绘制图片（主图 + 二维码）
    await drawImage(posterConfig.mainImage)
    await drawImage(posterConfig.qrcode)

    // 延迟确保绘制生效
    await new Promise(resolve => setTimeout(resolve, 200))
    await convertToImage()
    uni.showToast({ title: '海报生成成功', icon: 'success' })
  } catch (err) {
    console.error('生成失败：', err)
    uni.showToast({ title: `生成失败：${err.message}`, icon: 'none' })
  }
}

// 转图片（不变）
const convertToImage = () => {
  return new Promise((resolve, reject) => {
    if (!canvasNode) return reject('Canvas 节点不存在')
    uni.canvasToTempFilePath({
      canvas: canvasNode,
      width: canvasWidth.value,
      height: canvasHeight.value,
      destWidth: canvasWidth.value * 2,
      destHeight: canvasHeight.value * 2,
      success: (res) => {
        posterUrl.value = res.tempFilePath
        resolve()
      },
      fail: (err) => {
        reject(`转图片失败：${err.errMsg}`)
      }
    }, instance)
  })
}

// 保存相册相关方法（不变）
const saveToAlbum = () => {
  if (!posterUrl.value) return
  uni.getSetting({
    success: (res) => {
      if (!res.authSetting['scope.writePhotosAlbum']) {
        uni.authorize({
          scope: 'scope.writePhotosAlbum',
          success: saveImage,
          fail: () => {
            uni.showModal({
              title: '权限申请',
              content: '需要相册权限才能保存海报',
              success: (modalRes) => modalRes.confirm && uni.openSetting()
            })
          }
        })
      } else {
        saveImage()
      }
    }
  })
}

const saveImage = () => {
  uni.saveImageToPhotosAlbum({
    filePath: posterUrl.value,
    success: () => uni.showToast({ title: '保存成功', icon: 'success' }),
    fail: (err) => {
      console.error('保存失败：', err)
      uni.showToast({ title: '保存失败', icon: 'none' })
    }
  })
}
</script>

<style scoped>
/* 样式不变 */
.poster-page {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20rpx;
}
.canvas-hidden {
  position: absolute;
  left: -9999rpx;
  top: -9999rpx;
  z-index: -1;
  width: 375px;
  height: 667px;
}
.preview-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}
.poster-img {
  width: 100%;
  border-radius: 16rpx;
  box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.1);
}
.generate-btn, .save-btn {
  width: 600rpx;
  height: 88rpx;
  line-height: 88rpx;
  margin-top: 40rpx;
  background-color: #07c160;
  color: #ffffff;
  font-size: 32rpx;
  border-radius: 44rpx;
}
.save-btn {
  background-color: #1677ff;
  margin-top: 20rpx;
}
</style>