<script setup lang="ts">
import type { KonvaMarkingData, MarkingTool } from '../../composables/renderer/useMarkingKonva'
import Konva from 'konva'

import { useMessage } from 'wot-design-uni'
import { useSimpleKonvaLayer } from '../../composables/renderer/useMarkingKonva'

interface Props {
  imageUrl: string
  scale?: number
  markingData?: KonvaMarkingData
  backgroundColor?: string
  currentTool: MarkingTool
  readOnly?: boolean
  adaptiveWidth?: boolean // 是否启用自适应宽度模式
  onQuickScore?: (value: number) => boolean
}

const props = withDefaults(defineProps<Props>(), {
  scale: 1,
  backgroundColor: '#ffffff',
  readOnly: false,
  adaptiveWidth: false,
})

const emit = defineEmits<{
  'layer-ready': [layerManager: ReturnType<typeof useSimpleKonvaLayer>]
  'quick-score': [value: number]
}>()

const scale = computed(() => {
  return props.scale
})

const currentTool = computed(() => {
  return props.currentTool
})

// Refs
const containerRef = ref<HTMLDivElement>()
const konvaContainer = ref<HTMLDivElement>()

// Konva实例
let stage: Konva.Stage | null = null
let layer: Konva.Layer | null = null

// 图片的自然尺寸
const naturalWidth = ref(0)
const naturalHeight = ref(0)

// 容器尺寸
const containerWidth = ref(0)
const containerHeight = ref(0)

// 计算实际使用的缩放比例
const actualScale = computed(() => {
  if (!props.adaptiveWidth || !naturalWidth.value || !containerWidth.value) {
    return props.scale
  }

  // 自适应宽度模式：计算适合容器宽度的缩放比例
  const adaptiveScale = containerWidth.value / naturalWidth.value
  return Math.min(adaptiveScale, props.scale) // 不超过原始设定的缩放比例
})

// 计算容器样式
const containerStyle = computed(() => {
  if (!naturalWidth.value || !naturalHeight.value) {
    return {
      width: props.adaptiveWidth ? '100%' : '100%',
      height: '400px',
      backgroundColor: props.backgroundColor,
    }
  }

  if (props.adaptiveWidth) {
    // 自适应模式：容器宽度100%，高度根据比例计算
    const scaledHeight = naturalHeight.value * actualScale.value
    return {
      width: '100%',
      height: `${scaledHeight}px`,
      backgroundColor: props.backgroundColor,
    }
  }
  else {
    // 固定缩放模式：根据缩放比例设置固定尺寸
    const scaledWidth = naturalWidth.value * actualScale.value
    const scaledHeight = naturalHeight.value * actualScale.value
    return {
      width: `${scaledWidth}px`,
      height: `${scaledHeight}px`,
      backgroundColor: props.backgroundColor,
    }
  }
})

// Layer管理器
let layerManager: ReturnType<typeof useSimpleKonvaLayer> | null = null
const message = useMessage()

/**
 * 更新容器尺寸
 */
function updateContainerSize() {
  if (!konvaContainer.value)
    return

  containerWidth.value = konvaContainer.value.offsetWidth
  containerHeight.value = konvaContainer.value.offsetHeight
}

/**
 * 初始化Konva画布
 */
async function initKonva() {
  if (!konvaContainer.value)
    return

  // 等待容器尺寸稳定
  await nextTick()

  // 更新容器尺寸
  updateContainerSize()

  const currentContainerWidth = containerWidth.value
  const currentContainerHeight = containerHeight.value

  // 创建Stage
  const newStage = new Konva.Stage({
    container: konvaContainer.value,
    width: currentContainerWidth,
    height: currentContainerHeight,
  })

  // 创建Layer
  const newLayer = new Konva.Layer()
  newStage.add(newLayer)

  stage = newStage
  layer = newLayer

  // 加载图片
  await loadImage()

  // 创建layer管理器
  layerManager = useSimpleKonvaLayer({
    layer: newLayer,
    scale: actualScale,
    currentTool,
    initialData: props.markingData,
    onQuickScore: (value: number) => props.onQuickScore?.(value),
    readOnly: props.readOnly,
    message,
  })

  // 只有在非只读模式下才初始化事件
  if (!props.readOnly) {
    layerManager.initializeEvents()
  }

  // 如果有初始数据，渲染它
  if (props.markingData) {
    layerManager.renderMarkingData()
  }

  // 触发ready事件
  emit('layer-ready', layerManager)
}

/**
 * 加载图片
 */
async function loadImage(): Promise<void> {
  return new Promise((resolve, reject) => {
    const img = new Image()

    img.onload = () => {
      if (!layer || !stage) {
        reject(new Error('Konva not initialized'))
        return
      }

      // 记录图片自然尺寸
      naturalWidth.value = img.naturalWidth
      naturalHeight.value = img.naturalHeight

      // 创建Konva图片节点
      const image = new Konva.Image({
        x: 0,
        y: 0,
        image: img,
        width: img.naturalWidth,
        height: img.naturalHeight,
      })

      // 清空layer并添加图片
      layer.destroyChildren()
      layer.add(image)

      // 应用缩放和标记数据
      applyScale()

      layer.draw()
      resolve()
    }

    img.onerror = () => {
      reject(new Error(`Failed to load image: ${props.imageUrl}`))
    }

    img.src = props.imageUrl
  })
}

/**
 * 应用缩放
 */
function applyScale() {
  if (!layer || !stage)
    return

  const currentScale = actualScale.value

  // 重置layer的变换
  layer.scale({ x: currentScale, y: currentScale })
  layer.offset({ x: 0, y: 0 })
  layer.position({ x: 0, y: 0 })

  // 更新stage尺寸
  if (props.adaptiveWidth && containerWidth.value) {
    // 自适应模式：stage宽度等于容器宽度
    const scaledHeight = naturalHeight.value * currentScale
    stage.size({
      width: containerWidth.value,
      height: scaledHeight,
    })
  }
  else {
    // 固定缩放模式：根据缩放比例设置尺寸
    const scaledWidth = naturalWidth.value * currentScale
    const scaledHeight = naturalHeight.value * currentScale
    stage.size({
      width: scaledWidth,
      height: scaledHeight,
    })
  }

  layer.draw()
}

/**
 * 获取layer管理器
 */
const getLayerManager = () => layerManager

// 监听图片URL变化
watch(
  () => props.imageUrl,
  async () => {
    if (stage && layer) {
      await loadImage()
    }
  },
  { immediate: false },
)

// 监听缩放变化
watch([() => props.scale, actualScale], () => {
  applyScale()
})

// 监听容器尺寸变化（自适应模式）
watch(
  () => props.adaptiveWidth,
  (newAdaptiveWidth) => {
    if (newAdaptiveWidth && konvaContainer.value) {
      // 开启自适应模式时重新计算容器尺寸
      nextTick(() => {
        updateContainerSize()
        applyScale()
      })
    }
  },
)

// ResizeObserver实例 - 用于小程序环境的兼容性
let resizeObserver: any = null

/**
 * 设置尺寸监听器（适配小程序）
 */
function setupResizeObserver() {
  if (!props.adaptiveWidth || !containerRef.value)
    return

  // 在小程序环境中，ResizeObserver 可能不可用，使用定时器作为备选方案
  if (typeof ResizeObserver !== 'undefined') {
    resizeObserver = new ResizeObserver((entries) => {
      for (const entry of entries) {
        const { width, height } = entry.contentRect
        containerWidth.value = width
        containerHeight.value = height

        // 延迟应用缩放以确保DOM更新完成
        nextTick(() => {
          applyScale()
        })
      }
    })

    resizeObserver.observe(containerRef.value)
  }
  else {
    // 小程序环境备选方案：使用定时器监听尺寸变化
    let lastWidth = 0
    let lastHeight = 0

    const checkSizeChange = () => {
      if (!containerRef.value)
        return

      const newWidth = containerRef.value.offsetWidth || 0
      const newHeight = containerRef.value.offsetHeight || 0

      if (newWidth !== lastWidth || newHeight !== lastHeight) {
        lastWidth = newWidth
        lastHeight = newHeight
        containerWidth.value = newWidth
        containerHeight.value = newHeight

        nextTick(() => {
          applyScale()
        })
      }
    }

    resizeObserver = setInterval(checkSizeChange, 500) // 每500ms检查一次
  }
}

/**
 * 清理尺寸监听器
 */
function cleanupResizeObserver() {
  if (resizeObserver) {
    if (typeof ResizeObserver !== 'undefined' && resizeObserver.disconnect) {
      resizeObserver.disconnect()
    }
    else if (typeof resizeObserver === 'number') {
      clearInterval(resizeObserver)
    }
    resizeObserver = null
  }
}

// 暴露方法给父组件
defineExpose({
  getLayerManager,
  getStage: () => stage,
  getLayer: () => layer,
  updateContainerSize,
})

// 组件挂载时初始化
onMounted(async () => {
  await initKonva()
  // 在自适应模式下设置尺寸监听器
  if (props.adaptiveWidth) {
    setupResizeObserver()
  }
})

// 组件卸载时清理
onUnmounted(() => {
  layerManager?.cleanupEvents()
  cleanupResizeObserver()
  stage?.destroy()
})
</script>

<template>
  <div ref="containerRef" class="konva-image-renderer relative" :style="containerStyle">
    <div ref="konvaContainer" class="h-full w-full" />
  </div>
</template>

<style scoped>
.konva-image-renderer {
  display: inline-block;
  overflow: hidden;
}
</style>
