<script setup lang="ts">
import type { MarkingSubmitData } from '../../composables/useMarkingData'
import { useSessionStorage } from '@vueuse/core'
import { DictCode, useDict } from '@/composables/useDict'
import { MarkingTool } from '../../composables/renderer/useMarkingDom'
import { markingSettings as settings } from '../../composables/useMarkingSettings'

interface Props {
  canUndo?: boolean
  canRedo?: boolean
  hasMarks?: boolean
  specialMarks?: {
    excellent: boolean
    typical: boolean
    problem: boolean
  }
  isLandscape?: boolean
  currentMarkingData?: MarkingSubmitData
}

const props = withDefaults(defineProps<Props>(), {
  canUndo: false,
  canRedo: false,
  hasMarks: false,
  specialMarks: () => ({
    excellent: false,
    typical: false,
    problem: false,
  }),
  isLandscape: false,
})

const emit = defineEmits<{
  'add-correct-mark': [position: { x: number, y: number }]
  'add-wrong-mark': [position: { x: number, y: number }]
  'add-half-mark': [position: { x: number, y: number }]
  'undo': []
  'redo': []
  'clear-all': []
  'toggle-special-mark': [type: 'excellent' | 'typical' | 'problem']
}>()
const currentTool = defineModel<MarkingTool>('currentTool', { required: true })
const showToolOptions = computed(() => {
  return [MarkingTool.PEN, MarkingTool.TEXT].includes(currentTool.value)
})

// 工具栏引用
const toolbarRef = ref<HTMLElement>()

// 工具栏位置状态，使用 SessionStorage 持久化，默认位于左下角
const position = useSessionStorage('marking-toolbar-position', { x: 16, y: 16 })

// 收起状态
const isCollapsed = useSessionStorage('marking-toolbar-collapsed', false)

// 拖动状态
const isDragging = ref(false)
const dragState = ref({
  startX: 0,
  startY: 0,
  startPositionX: 0,
  startPositionY: 0,
})

const { getDictOptionsComputed } = useDict()
const { options: problemTypeOptions } = getDictOptionsComputed(DictCode.SCAN_ANOMALY_STATUS)
const problemTooltipContent = computed(() => {
  if (props.currentMarkingData?.isProblem) {
    return `当前问题类型：${problemTypeOptions.value.find(item => item.value === props.currentMarkingData?.problemType)?.label}`
  }
  return '标记为问题卷'
})

/**
 * 将 SVG 转换为 data URL（用于小程序）
 */
function svgToDataURL(svg: string): string {
  // 将被设置到 dataset 中的属性还原出来
  svg = svg.replace(/data-(.*?=(['"]).*?\2)/g, '$1')

  // 将被设置到 data-xlink-href 的属性还原出来
  svg = svg.replace(/xlink-href=/g, 'xlink:href=')

  // 将 dataset 中被变成 kebab-case 写法的 viewBox 还原出来
  svg = svg.replace(/view-box=/g, 'viewBox=')

  // 清除 SVG 中不应该显示的 title、desc、defs 元素
  svg = svg.replace(/<(title|desc|defs)>[\s\S]*?<\/\1>/g, '')

  // 为非标准 XML 的 SVG 添加 xmlns，防止视图层解析出错
  if (!/xmlns=/.test(svg))
    svg = svg.replace(/<svg/, '<svg xmlns=\'http://www.w3.org/2000/svg\'')

  // 对 SVG 中出现的浮点数统一取最多两位小数，缓解数据量过大问题
  svg = svg.replace(/\d+\.\d+/g, match => Number.parseFloat(Number.parseFloat(match).toFixed(2)) as any)

  // 清除注释，缓解数据量过大的问题
  svg = svg.replace(/<!--[\s\S]*?-->/g, '')

  // 模拟 HTML 的 white-space 行为，将多个空格或换行符换成一个空格，减少数据量
  svg = svg.replace(/\s+/g, ' ')

  // 对特殊符号进行转义，这里参考了 https://github.com/bhovhannes/svg-url-loader/blob/master/src/loader.js
  svg = svg.replace(/[{}|\\^~[\]`"<>#%]/g, (match) => {
    return `%${match[0].charCodeAt(0).toString(16).toUpperCase()}`
  })

  // 单引号替换为 \'，由于 kbone 的 bug，节点属性中的双引号在生成 outerHTML 时不会被转义导致出错
  // 因此 background-image: url( 后面只能跟单引号，所以生成的 URI 内部也就只能用斜杠转义单引号了
  svg = svg.replace(/'/g, '\\\'')

  // 最后添加 mime 头部，变成 Webview 可以识别的 Data URI
  return `data:image/svg+xml,${svg.trim()}`
}

/**
 * 生成半对标记的 SVG data URL
 * 根据当前按钮状态动态生成颜色
 */
function generateHalfMarkSvg(isActive: boolean): string {
  // 根据激活状态选择颜色
  const color = isActive ? '#ffffff' : '#eab308' // 白色（激活）或黄色（未激活）
  const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
    <line x1="6" y1="12" x2="10.5" y2="16.5" stroke="${color}" stroke-width="2" stroke-linecap="round" fill="none"/>
    <line x1="10.5" y1="16.5" x2="18" y2="7.5" stroke="${color}" stroke-width="2" stroke-linecap="round" fill="none"/>
    <line x1="11.25" y1="9.38" x2="17.25" y2="15" stroke="${color}" stroke-width="2" stroke-linecap="round" fill="none"/>
  </svg>`
  return svgToDataURL(svg)
}

const halfMarkSvg = computed(() => {
  const isActive = currentTool.value === MarkingTool.HALF
  return generateHalfMarkSvg(isActive)
})

// 待放置标记的状态
const pendingMarkType = ref<'correct' | 'wrong' | 'half' | null>(null)

// 统一的按钮基础样式
const baseButtonClass = computed(() => {
  return props.isLandscape
    ? 'size-32rpx lg:size-8 !p-0 rounded-lg flex items-center justify-center transition-all duration-200 ease-in-out shadow-sm hover:shadow-md active:scale-95 after:border-none'
    : 'size-8 lg:size-10 !p-0 rounded-lg flex items-center justify-center transition-all duration-200 ease-in-out shadow-sm hover:shadow-md active:scale-95 after:border-none'
})

const separatorClass = computed(() => {
  return props.isLandscape
    ? 'mx-4rpx lg:mx-1 h-4 lg:h-6 w-px flex-shrink-0 bg-gray-300'
    : 'h-5 lg:h-6 w-px bg-gray-300'
})
const iconClass = computed(() => {
  return props.isLandscape
    ? 'size-20rpx lg:size-4'
    : 'size-5 lg:size-5 w-4 lg:w-5'
})

/**
 * 获取工具按钮样式类
 */
function getToolButtonClass(tool: MarkingTool) {
  const isActive = currentTool.value === tool
  return [
    baseButtonClass.value,
    isActive
      ? 'bg-blue-600 text-white border border-blue-500'
      : 'bg-white text-blue-600 border border-blue-200 hover:bg-blue-50 hover:border-blue-300 hover:text-blue-700',
  ]
}

/**
 * 获取标记按钮样式类（对错半对）
 */
function getMarkButtonClass(type: 'correct' | 'wrong' | 'half') {
  const toolMap = {
    correct: MarkingTool.CORRECT,
    wrong: MarkingTool.WRONG,
    half: MarkingTool.HALF,
  }
  const colorMap = {
    correct: {
      active: 'bg-green-500 text-white border border-green-400',
      inactive: 'bg-white text-green-600 border border-green-200 hover:bg-green-50 hover:border-green-300 hover:text-green-700',
    },
    wrong: {
      active: 'bg-red-500 text-white border border-red-400',
      inactive: 'bg-white text-red-600 border border-red-200 hover:bg-red-50 hover:border-red-300 hover:text-red-700',
    },
    half: {
      active: 'bg-yellow-500 text-white border border-yellow-400',
      inactive: 'bg-white text-yellow-600 border border-yellow-200 hover:bg-yellow-50 hover:border-yellow-300 hover:text-yellow-700',
    },
  }

  const isActive = currentTool.value === toolMap[type]
  const colors = colorMap[type]

  return [baseButtonClass.value, isActive ? colors.active : colors.inactive]
}

/**
 * 获取特殊标记按钮样式类
 */
function getSpecialButtonClass(type: 'excellent' | 'typical' | 'problem') {
  const isActive = props.specialMarks[type]
  const colorMap = {
    excellent: {
      active: 'bg-yellow-500 text-white border border-yellow-400',
      inactive: 'bg-white text-yellow-600 border border-yellow-200 hover:bg-yellow-50 hover:border-yellow-300 hover:text-yellow-700',
    },
    typical: {
      active: 'bg-blue-600 text-white border border-blue-500',
      inactive: 'bg-white text-blue-600 border border-blue-200 hover:bg-blue-50 hover:border-blue-300 hover:text-blue-700',
    },
    problem: {
      active: 'bg-red-500 text-white border border-red-400',
      inactive: 'bg-white text-red-600 border border-red-200 hover:bg-red-50 hover:border-red-300 hover:text-red-700',
    },
  }

  const colors = colorMap[type]
  return [baseButtonClass.value, props.isLandscape ? 'text-12rpx lg:text-sm' : 'text-sm lg:text-base', 'font-medium', isActive ? colors.active : colors.inactive]
}

/**
 * 切换工具（支持取消激活）
 */
function switchTool(tool: MarkingTool) {
  currentTool.value = currentTool.value === tool ? MarkingTool.SELECT : tool
  pendingMarkType.value = null

  // 显示/隐藏工具选项
  settings.value.showToolOptions = currentTool.value === 'pen' || currentTool.value === 'text'
}

/**
 * 处理标记工具切换（正确/错误/半对）
 */
function handleMarkTool(type: 'correct' | 'wrong' | 'half') {
  const toolMap = {
    correct: MarkingTool.CORRECT,
    wrong: MarkingTool.WRONG,
    half: MarkingTool.HALF,
  }
  const tool = toolMap[type]
  currentTool.value = currentTool.value === tool ? MarkingTool.SELECT : tool
  pendingMarkType.value = null
}

/**
 * 处理图片点击（用于放置标记）
 */
function handleImageClick(position: { x: number, y: number }) {
  if (pendingMarkType.value) {
    switch (pendingMarkType.value) {
      case 'correct':
        emit('add-correct-mark', position)
        break
      case 'wrong':
        emit('add-wrong-mark', position)
        break
      case 'half':
        emit('add-half-mark', position)
        break
    }

    pendingMarkType.value = null
  }
}

/**
 * 处理撤销
 */
function handleUndo() {
  if (props.canUndo) {
    emit('undo')
  }
}

/**
 * 处理重做
 */
function handleRedo() {
  if (props.canRedo) {
    emit('redo')
  }
}

/**
 * 处理清除所有
 */
function handleClearAll() {
  if (props.hasMarks) {
    uni.showModal({
      confirmButtonText: '确认清除',
      cancelButtonText: '取消',
      success: (result) => {
        if (result.confirm) {
          emit('clear-all')
        }
      },
    })
  }
}

/**
 * 切换特殊标记
 */
function toggleSpecialMark(type: 'excellent' | 'typical' | 'problem') {
  emit('toggle-special-mark', type)
}

/**
 * 切换收起/展开状态
 */
function toggleCollapse() {
  isCollapsed.value = !isCollapsed.value
}

// 暴露点击处理方法给父组件
defineExpose({
  handleImageClick,
})
</script>

<template>
  <div
    ref="toolbarRef"
    class="rounded-tr-base fixed bottom-0 left-0 z-10 select-none border border-white/20 shadow-xl backdrop-blur-sm transition-all duration-300"
    :class="[
      {
        'px-2 py-1 w-fit cursor-move lg:px-3 lg:py-2': !isLandscape && !isCollapsed,
        'px-4rpx py-2rpx': isLandscape && !isCollapsed,
        'bg-slate-800/95': !isCollapsed,
        'backdrop-saturate-150': !isCollapsed,
      },
    ]"
  >
    <!-- 收起按钮 -->
    <div
      v-if="isCollapsed"
      class="h-full w-8 flex transform cursor-pointer items-center justify-center border border-gray-200 rounded-tr-2xl bg-white shadow-inner"
      :class="{
        'w-64px': isLandscape,
      }"
      @click="toggleCollapse"
      @mousedown.stop
    >
      <div class="i-carbon:chevron-right text-base text-blue-600 transition-colors lg:text-lg hover:text-blue-700" />
    </div>

    <!-- 工具栏内容 -->
    <div
      v-show="!isCollapsed"
      class="flex items-center" :class="{
        'gap-4rpx lg:gap-2': !isLandscape,
        'gap-4rpx lg:gap-1': isLandscape,
      }"
    >
      <!-- 收起按钮（展开状态时显示） -->
      <button
        class="border border-gray-200 bg-white text-slate-600 transition-all hover:border-gray-300 hover:bg-gray-50 hover:text-slate-700"
        :class="baseButtonClass"
        @click="toggleCollapse"
      >
        <div :class="iconClass" class="i-carbon:chevron-left" />
      </button>

      <div :class="separatorClass" />
      <!-- 对错半对标记 -->
      <wd-tooltip content="正确标记" placement="top">
        <button :class="getMarkButtonClass('correct')" @click="handleMarkTool('correct')">
          <div :class="iconClass" class="i-fluent:checkmark-24-regular" />
        </button>
      </wd-tooltip>

      <wd-tooltip content="错误标记" placement="top">
        <button :class="getMarkButtonClass('wrong')" @click="handleMarkTool('wrong')">
          <div :class="iconClass" class="i-fluent:dismiss-24-regular" />
        </button>
      </wd-tooltip>

      <wd-tooltip content="半对标记" placement="top">
        <button :class="getMarkButtonClass('half')" @click="handleMarkTool('half')">
          <view
            class="h-48rpx w-48rpx" :class="iconClass"
            :style="{
              backgroundImage: `url('${halfMarkSvg}')`,
              backgroundSize: 'contain',
              backgroundRepeat: 'no-repeat',
              backgroundPosition: 'center',
            }"
          />
        </button>
      </wd-tooltip>

      <div :class="separatorClass" />
      <!-- 橡皮擦 -->
      <wd-tooltip content="擦除" placement="top">
        <button
          :class="getToolButtonClass(MarkingTool.ERASER)"
          @click="switchTool(MarkingTool.ERASER)"
        >
          <div :class="iconClass" class="i-fluent:eraser-24-regular" />
        </button>
      </wd-tooltip>

      <!-- 文字工具 -->
      <wd-tooltip content="添加文字" placement="top">
        <button :class="getToolButtonClass(MarkingTool.TEXT)" @click="switchTool(MarkingTool.TEXT)">
          <div :class="iconClass" class="i-fluent:text-24-regular" />
        </button>
      </wd-tooltip>

      <!-- 任意笔画 -->
      <wd-tooltip content="自由绘制" placement="top">
        <button :class="getToolButtonClass(MarkingTool.PEN)" @click="switchTool(MarkingTool.PEN)">
          <div :class="iconClass" class="i-fluent:pen-24-regular" />
        </button>
      </wd-tooltip>

      <div :class="separatorClass" />

      <!-- 撤回 -->
      <!-- <wd-tooltip content="撤回一步" placement="top">
        <button :class="getActionButtonClass('undo')" :disabled="!canUndo" @click="handleUndo">
          <div class="i-fluent:arrow-undo-24-regular h-4 w-4" />
        </button>
      </wd-tooltip> -->

      <!-- 特殊标记 -->
      <wd-tooltip content="标记为优秀卷" placement="top">
        <button
          :class="getSpecialButtonClass('excellent')"
          @click="toggleSpecialMark('excellent')"
        >
          优秀
        </button>
      </wd-tooltip>

      <wd-tooltip content="标记为典例卷" placement="top">
        <button
          :class="getSpecialButtonClass('typical')"
          @click="toggleSpecialMark('typical')"
        >
          典例
        </button>
      </wd-tooltip>

      <wd-tooltip :content="problemTooltipContent" placement="top">
        <button
          :class="getSpecialButtonClass('problem')"
          @click="toggleSpecialMark('problem')"
        >
          问题
        </button>
      </wd-tooltip>
    </div>
  </div>
</template>
