<script setup lang="ts">
import type { DomMarkingData, useSimpleDomLayer } from '../../composables/renderer/useMarkingDom'
import { DictCode, useDict } from '@/composables/useDict'
import { MarkingTool } from '../../composables/renderer/useMarkingDom'
import { useMarkingData } from '../../composables/useMarkingData'
import { markingSettings } from '../../composables/useMarkingSettings'
import { useSimpleMarkingTool } from '../../composables/useSimpleMarkingTool'
import ProblemSheetDialog from '../dialog/ProblemSheetDialog.vue'
import DomImageRenderer from './DomImageRenderer.vue'
import TraceToolbar from './TraceToolbar.vue'

interface Question {
  id: string
  title: string
  fullScore: number
  imageUrls: string[]
}

interface Props {
  question: Question
  questionIndex?: number
  scale?: number
  imageLayout?: 'horizontal' | 'vertical'
  showToolbar?: boolean
  initialMarkingData?: DomMarkingData[]
}

const props = withDefaults(defineProps<Props>(), {
  questionIndex: 0,
  scale: 1,
  imageLayout: 'horizontal',
  showToolbar: true,
})

const emit = defineEmits<{
  'marking-change': [imageIndex: number, data: DomMarkingData]
}>()

const { currentTool } = useSimpleMarkingTool()
const markingData = useMarkingData()

// layer管理器
const layerManagers = ref<Map<number, ReturnType<typeof useSimpleDomLayer>>>(new Map())

// 每个图片的标记数据
const markingDataList = ref<DomMarkingData[]>(
  props.question.imageUrls.map(
    (_, index) =>
      props.initialMarkingData?.[index] || {
        version: '1.0',
        shapes: [],
        specialMarks: [],
        annotations: [],
      },
  ),
)

const currentMarkingData = computed({
  get: () => {
    return markingData.currentMarkingSubmitData.value[props.questionIndex]
  },
  set: (value) => {
    markingData.currentMarkingSubmitData.value[props.questionIndex] = value
  },
})

const specialMarks = computed(() => {
  const data = currentMarkingData.value
  return {
    excellent: data?.isExcellent ?? false,
    typical: data?.isTypical ?? false,
    problem: data?.isProblem ?? false,
  }
})

const operateLayerStack = ref<number[]>([])

const canUndo = computed(() => {
  return Array.from(layerManagers.value.values()).some(manager => manager.canUndo)
})

const hasMarks = computed(() => {
  return Array.from(layerManagers.value.values()).some(manager => manager.hasMarks)
})

/**
 * 处理layer准备就绪
 */
function handleLayerReady(imageIndex: number, manager: ReturnType<typeof useSimpleDomLayer>) {
  layerManagers.value.set(imageIndex, manager as any)

  // 监听标记数据变化
  watch(
    manager.markingData,
    (newData) => {
      markingDataList.value[imageIndex] = { ...newData }
      currentMarkingData.value.remark = markingDataList.value
      operateLayerStack.value.push(imageIndex)
      emit('marking-change', imageIndex, newData)
    },
    { deep: true },
  )
}

/**
 * 清空所有标记
 */
function clearAllMarks() {
  layerManagers.value.forEach((manager) => {
    manager.clearAllMarks()
  })
}

/**
 * 撤销操作
 */
function undo() {
  const imageIndex = operateLayerStack.value.pop()
  if (imageIndex !== undefined) {
    layerManagers.value.get(imageIndex)?.undo()
  }
}

/**
 * 处理快捷打分
 */
function handleQuickScore(value: number) {
  if (currentTool.value !== MarkingTool.SELECT || !markingSettings.value.quickScoreClickMode) {
    return false
  }

  if (currentMarkingData.value) {
    const currentScore
      = currentMarkingData.value.score === -1
        ? markingSettings.value.scoreMode === 'subtract'
          ? props.question.fullScore
          : 0
        : currentMarkingData.value.score

    if (value > 0 && currentScore >= props.question.fullScore) {
      return false
    }
    if (value < 0 && currentScore <= 0) {
      return false
    }

    const newScore = Math.max(0, Math.min(props.question.fullScore, currentScore + value))
    currentMarkingData.value.score = newScore
    return true
  }

  return false
}

/**
 * 处理文本输入
 */
async function handleTextInput(pos: { x: number, y: number }): Promise<string | null> {
  return new Promise((resolve) => {
    uni.showModal({
      title: '请输入文字',
      editable: true,
      placeholderText: '请输入文字内容',
      success: (res) => {
        if (res.confirm && res.content) {
          resolve(res.content)
        }
        else {
          resolve(null)
        }
      },
      fail: () => {
        resolve(null)
      },
    })
  })
}

// 问题卷对话框引用
const problemSheetDialogRef = ref<InstanceType<typeof ProblemSheetDialog>>()

const { getDictOptionsComputed } = useDict()
const { options: problemTypeOptions } = getDictOptionsComputed(DictCode.SCAN_ANOMALY_STATUS)

const problemTypeText = computed(() => {
  return (
    problemTypeOptions.value.find(item => item.value === currentMarkingData.value.problemType)
      ?.label ?? ''
  )
})

const currentSpecialMarkText = computed(() => {
  if (currentMarkingData.value.isExcellent) {
    return '优秀试卷'
  }
  if (currentMarkingData.value.isTypical) {
    return '典型试卷'
  }
  if (currentMarkingData.value.isProblem) {
    return `问题试卷 - ${problemTypeText.value}`
  }
  return ''
})

const specialMarkTypeMap = {
  excellent: '优秀试卷',
  typical: '典型试卷',
  problem: '问题试卷',
} as const

async function toggleSpecialMark(type: 'excellent' | 'typical' | 'problem') {
  // 如果当前已有特殊标记，需要用户确认是否更改
  if (currentSpecialMarkText.value) {
    const modalResult = await new Promise<boolean>((resolve) => {
      uni.showModal({
        title: '提示',
        content: `当前已经被标记为 ${currentSpecialMarkText.value}，是否改为${specialMarkTypeMap[type]}？`,
        success: (res) => {
          resolve(res.confirm)
        },
        fail: () => {
          resolve(false)
        },
      })
    })

    // 用户取消了更改
    if (!modalResult) {
      return
    }
  }

  if (type === 'problem') {
    try {
      problemSheetDialogRef.value?.syncFormData({
        problemType: currentMarkingData.value.problemType ?? '',
        problemRemark: currentMarkingData.value.problemRemark ?? '',
      })
      const result = await problemSheetDialogRef.value?.start()
      if (result) {
        Object.assign(markingData.currentMarkingSubmitData.value[props.questionIndex]!, {
          isExcellent: false,
          isTypical: false,
          isProblem: true,
          problemType: result.problemType,
          problemRemark: result.problemRemark,
          score: 0,
        })

        if (markingData.mode.value === 'single') {
          markingData.submitRecord()
        }
      }
    }
    catch (error) {
      if (error !== 'cancel') {
        console.error('标记问题卷失败:', error)
        uni.showToast({
          title: '标记问题卷失败',
          icon: 'none',
        })
      }
    }
    return
  }

  Object.assign(markingData.currentMarkingSubmitData.value[props.questionIndex]!, {
    isExcellent: type === 'excellent',
    isTypical: type === 'typical',
    isProblem: false,
    problemType: undefined,
    problemRemark: undefined,
  })
}

onMounted(() => {
  markingData.currentMarkingSubmitData.value[props.questionIndex] = {
    score: -1,
    remark: props.question.imageUrls.map(() => ({})),
    status: 'draft',
    isExcellent: false,
    isTypical: false,
    isProblem: false,
    problemType: '',
    problemRemark: '',
  }
})

// 暴露方法给父组件
defineExpose({
  clearAllMarks,
  undo,
})
</script>

<template>
  <view
    v-if="
      markingData.mode.value !== 'multi'
        || !markingSettings.hideMarked
        || currentMarkingData?.score === -1
    "
    class="question-renderer"
    :class="{
      'ring-2 ring-red-500':
        markingData.mode.value === 'multi'
        && markingData.firstNotScoredIndex.value === questionIndex,
    }"
  >
    <!-- 图片容器 -->
    <view
      class="flex"
      :class="imageLayout === 'horizontal' ? 'flex-row' : 'flex-col'"
      :style="{ gap: '16px' }"
    >
      <view
        v-for="(imageUrl, imageIndex) in question.imageUrls"
        :key="`${question.id}_${imageIndex}`"
        class="relative"
      >
        <DomImageRenderer
          :image-url="imageUrl"
          :scale="scale"
          :marking-data="markingDataList[imageIndex]"
          :current-tool="currentTool"
          :on-text-input="handleTextInput"
          @layer-ready="(manager) => handleLayerReady(imageIndex, manager)"
          @quick-score="handleQuickScore"
        />

        <!-- 第一个图片显示分数 -->
        <view
          v-if="
            imageIndex === 0
              && currentMarkingData?.score !== undefined
              && currentMarkingData?.score !== -1
          "
          class="absolute left-2 top-2 z-10 flex items-baseline"
          :style="{ gap: '2px', textShadow: '1px 1px 2px rgba(0, 0, 0, 0.3)' }"
        >
          <text class="text-3xl text-red-600 font-bold">{{ currentMarkingData.score }}</text>
          <text class="text-lg text-red-500 font-semibold">/{{ question.fullScore }}</text>
        </view>
      </view>
    </view>

    <!-- 工具栏 -->
    <TraceToolbar
      v-if="showToolbar && markingData.firstNotScoredIndex.value === questionIndex"
      v-model:current-tool="currentTool"
      :can-undo="canUndo"
      :has-marks="hasMarks"
      :special-marks="specialMarks"
      :current-marking-data="currentMarkingData"
      :is-landscape="markingData.isLandscape.value"
      @undo="undo"
      @clear-all="clearAllMarks"
      @toggle-special-mark="toggleSpecialMark"
    />

    <!-- 问题卷对话框 -->
    <ProblemSheetDialog ref="problemSheetDialogRef" />
  </view>
</template>
