<!-- 带批注的答题卡查看器 - 简化独立组件 -->
<script setup lang="ts">
import type { AnswerSheetData } from './types.ts'
import Konva from 'konva'
import { useMarkingRenderer } from './composables/useMarkingRenderer'

defineOptions({ name: 'AnswerSheetWithMarking' })

const props = withDefaults(defineProps<Props>(), {
  loading: false,
  error: false,
})

interface Props {
  /** 答题卡数据 */
  data: AnswerSheetData | null
  /** 是否加载中 */
  loading?: boolean
  /** 错误信息 */
  error?: boolean
}

// DOM 引用 - 每页一个独立的容器
const scrollContainerRef = ref<HTMLElement | null>(null)

// 显示控制
const showTeacherName = ref(true)
const showScore = ref(true)

// 标记渲染器
const markingRenderer = useMarkingRenderer()

// 计算属性
const answerSheetImages = computed(() => props.data?.answerSheetImages || [])

// 缓存合成后的图片（带批注）
const composedImages = ref<Map<number, string>>(new Map())

// 页面状态映射 - 存储每个页面的 Konva 实例和状态
const pageStates = ref<Map<number, {
  stage: Konva.Stage | null
  layer: Konva.Layer | null
  imageNaturalSize: { width: number, height: number }
  scale: number
}>>(new Map())

// 获取指定页面的标记
function getMarkingsForPage(pageIndex: number) {
  if (!props.data?.markings)
    return []
  return props.data.markings.filter(m => m.imageIndex === pageIndex)
}

// 初始化单个页面的 Konva
function initPageKonva(pageIndex: number, container: HTMLElement, imgElement: HTMLImageElement) {
  const { naturalWidth, naturalHeight } = imgElement

  // 获取容器宽度（实际显示宽度）
  const containerWidth = scrollContainerRef.value?.clientWidth || container.parentElement?.clientWidth || window.innerWidth

  // 计算缩放比例
  const scale = containerWidth / naturalWidth

  // 计算显示尺寸
  const displayWidth = naturalWidth * scale
  const displayHeight = naturalHeight * scale

  console.log('[initPageKonva] 初始化 Konva:', {
    pageIndex,
    naturalWidth,
    naturalHeight,
    containerWidth,
    scale,
    displayWidth,
    displayHeight,
  })

  // 创建 Konva Stage - 使用实际显示尺寸
  const stage = new Konva.Stage({
    container: container as HTMLDivElement,
    width: displayWidth,
    height: displayHeight,
  })

  const layer = new Konva.Layer()
  stage.add(layer)

  // 保存状态
  pageStates.value.set(pageIndex, {
    stage,
    layer,
    imageNaturalSize: { width: naturalWidth, height: naturalHeight },
    scale,
  })

  // 渲染标记
  renderPageMarkings(pageIndex)
}

// 渲染单个页面的标记
function renderPageMarkings(pageIndex: number) {
  const state = pageStates.value.get(pageIndex)
  if (!state?.layer)
    return

  const markings = getMarkingsForPage(pageIndex)
  if (!markings.length)
    return

  // 清空图层
  state.layer.destroyChildren()

  // 渲染每个标记
  markings.forEach((marking) => {
    markingRenderer.renderMarking(state.layer as any, marking, {
      scale: state.scale,
      showScore: showScore.value,
      showTeacherName: showTeacherName.value,
    })
  })

  state.layer.batchDraw()
}

// 图片加载完成处理
function handleImageLoad(pageIndex: number, event: any) {
  const containerId = `konva-container-${pageIndex}`

  nextTick(() => {
    const container = document.getElementById(containerId)
    if (!container) {
      console.warn('[handleImageLoad] 未找到 Konva 容器:', containerId)
      return
    }

    // 从 event.detail 获取图片尺寸（uniapp image 组件）
    const detail = event.detail || {}
    const width = detail.width || 750
    const height = detail.height || 1000

    console.log('[handleImageLoad] 图片尺寸:', { pageIndex, width, height })

    const mockImg = {
      naturalWidth: width,
      naturalHeight: height,
    } as HTMLImageElement

    initPageKonva(pageIndex, container, mockImg)
  })
}

// 将指定页面的图片和批注合成为一张图片
async function composeImageWithMarkings(pageIndex: number): Promise<string> {
  // 如果已经合成过，直接返回缓存
  if (composedImages.value.has(pageIndex)) {
    return composedImages.value.get(pageIndex)!
  }

  const state = pageStates.value.get(pageIndex)
  if (!state?.stage) {
    // 如果没有批注，返回原图
    return answerSheetImages.value[pageIndex]
  }

  try {
    // 创建一个临时的 Stage 用于合成（使用原始尺寸，不缩放）
    const tempContainer = document.createElement('div')
    tempContainer.style.position = 'absolute'
    tempContainer.style.left = '-9999px'
    document.body.appendChild(tempContainer)

    const naturalWidth = state.imageNaturalSize.width
    const naturalHeight = state.imageNaturalSize.height

    // 创建临时 Stage（原始尺寸，无缩放）
    const tempStage = new Konva.Stage({
      container: tempContainer,
      width: naturalWidth,
      height: naturalHeight,
    })

    const tempLayer = new Konva.Layer()
    tempStage.add(tempLayer)

    // 先绘制原始图片
    const imageObj = new Image()
    imageObj.crossOrigin = 'anonymous' // 支持跨域

    await new Promise<void>((resolve, reject) => {
      imageObj.onload = () => {
        const konvaImage = new Konva.Image({
          image: imageObj,
          width: naturalWidth,
          height: naturalHeight,
        })
        tempLayer.add(konvaImage)

        // 渲染批注（使用 scale=1，因为是原始尺寸）
        const markings = getMarkingsForPage(pageIndex)
        markings.forEach((marking) => {
          markingRenderer.renderMarking(tempLayer as any, marking, {
            scale: 1, // 原始尺寸，不缩放
            showScore: showScore.value,
            showTeacherName: showTeacherName.value,
          })
        })

        tempLayer.batchDraw()
        resolve()
      }
      imageObj.onerror = reject
      imageObj.src = answerSheetImages.value[pageIndex]
    })

    // 将 Stage 转换为 DataURL
    const dataURL = tempStage.toDataURL({
      pixelRatio: 1, // 原始分辨率
      mimeType: 'image/jpeg',
      quality: 0.9,
    })

    // 清理临时元素
    tempStage.destroy()
    document.body.removeChild(tempContainer)

    // 缓存结果
    composedImages.value.set(pageIndex, dataURL)

    return dataURL
  }
  catch (error) {
    console.error('[composeImageWithMarkings] 合成失败:', error)
    // 失败时返回原图
    return answerSheetImages.value[pageIndex]
  }
}

// 打开图片预览 - 显示带批注的图片
async function openPreview(pageIndex: number) {
  // 显示加载提示
  uni.showLoading({
    title: '准备预览...',
    mask: true,
  })

  try {
    // 合成所有图片（包含批注）
    const composedUrls: string[] = []
    for (let i = 0; i < answerSheetImages.value.length; i++) {
      const composedUrl = await composeImageWithMarkings(i)
      composedUrls.push(composedUrl)
    }

    uni.hideLoading()

    // 预览合成后的图片
    uni.previewImage({
      urls: composedUrls,
      current: pageIndex,
      longPressActions: {
        itemList: ['保存图片'],
        success: (data) => {
          console.log(`选中了第${data.tapIndex}个按钮`)
        },
        fail: (err) => {
          console.log(err.errMsg)
        },
      },
    })
  }
  catch (error) {
    uni.hideLoading()
    uni.showToast({
      title: '预览失败',
      icon: 'none',
    })
    console.error('[openPreview] 预览失败:', error)
  }
}

// 监听显示选项变化，重新渲染所有页面
watch([showTeacherName, showScore], () => {
  // 清空缓存，因为显示选项改变了
  composedImages.value.clear()

  pageStates.value.forEach((_, pageIndex) => {
    renderPageMarkings(pageIndex)
  })
})

// 监听数据变化，清空缓存
watch(() => props.data, () => {
  composedImages.value.clear()
})

// 清理所有 Konva 实例
onBeforeUnmount(() => {
  pageStates.value.forEach((state) => {
    if (state.stage) {
      state.stage.destroy()
    }
  })
  pageStates.value.clear()
})
</script>

<template>
  <view class="answer-sheet-viewer h-full w-full flex flex-col bg-gray-50">
    <!-- 加载状态 -->
    <view v-if="loading" class="h-full flex items-center justify-center">
      <view class="text-center">
        <view class="mx-auto mb-4 h-10 w-10 animate-spin border-4 border-gray-200 border-t-blue-500 rounded-full" />
        <text class="text-gray-600">正在加载答题卡数据...</text>
      </view>
    </view>

    <!-- 错误状态 -->
    <view v-else-if="error" class="h-full flex items-center justify-center">
      <view class="text-center text-red-600">
        <text>加载失败，请重试</text>
      </view>
    </view>

    <!-- 答题卡显示 - 所有页面垂直排列 -->
    <scroll-view
      v-else-if="answerSheetImages.length > 0"
      ref="scrollContainerRef"
      scroll-y
      class="h-full w-full"
    >
      <view class="flex flex-col p-4 space-y-4">
        <!-- 循环渲染每一页 -->
        <view
          v-for="(imageUrl, pageIndex) in answerSheetImages"
          :key="pageIndex"
          class="relative overflow-hidden rounded-lg bg-white shadow-sm"
        >
          <!-- 页码标识 -->
          <view class="absolute left-2 top-2 z-20 rounded bg-black/50 px-2 py-1">
            <text class="text-xs text-white">第 {{ pageIndex + 1 }} 页</text>
          </view>

          <!-- 图片容器 -->
          <view class="relative w-full" @click="openPreview(pageIndex)">
            <!-- 答题卡图片 -->
            <image
              :src="imageUrl"
              mode="widthFix"
              class="block w-full"
              @load="(e) => handleImageLoad(pageIndex, e)"
            />

            <!-- Konva 画布容器 - 绝对定位，覆盖在图片上 -->
            <view
              :id="`konva-container-${pageIndex}`"
              class="pointer-events-none absolute left-0 top-0 w-full"
              :style="{ height: '100%' }"
            />
          </view>
        </view>
      </view>
    </scroll-view>

    <!-- 暂无数据 -->
    <view v-else class="h-full flex items-center justify-center">
      <text class="text-gray-400">暂无答题卡数据</text>
    </view>
  </view>
</template>

<style scoped>
.answer-sheet-viewer {
  user-select: none;
}
</style>
