<script setup lang="ts">
import { ref, reactive, watch, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { useI18n } from '../composables/useI18n'
import { useMessage } from '../composables/useMessage'
import DatePicker from './DatePicker.vue'
import GanttConfirmDialog from './GanttConfirmDialog.vue'
import MultiSelectPredecessor from './MultiSelectPredecessor.vue'
import ConfirmTimerDialog from './ConfirmTimerDialog.vue'
import type { Task } from '../models/classes/Task'
import '../styles/app.css'

interface AssigneeOption {
  key?: string | number
  value: string | number
  label: string
}

interface Props {
  visible: boolean
  task?: Task | null
  isEdit?: boolean
  onDelete?: (task: Task) => void
  assigneeOptions?: AssigneeOption[]
}

const props = withDefaults(defineProps<Props>(), {
  visible: false,
  task: null,
  isEdit: false,
  onDelete: undefined,
  assigneeOptions: () => [
    { value: 'zhangsan', label: '张三' },
    { value: 'lisi', label: '李四' },
    { value: 'wangwu', label: '王五' },
    { value: 'zhaoliu', label: '赵六' },
    { value: 'qianqi', label: '钱七' },
  ],
})

const emit = defineEmits<{
  'update:visible': [value: boolean]
  submit: [task: Task]
  close: []
  delete: [task: Task, deleteChildren?: boolean]
  'start-timer': [task: Task]
  'stop-timer': [task: Task]
}>()

const { t } = useI18n()
const { showMessage } = useMessage()

const submitting = ref(false)
const isVisible = ref(props.visible)
const showDeleteConfirm = ref(false)

// 计时器相关
const timerElapsed = ref(0)
const timerInterval = ref<number | null>(null)

const isTimerRunning = computed(() => props.task?.isTimerRunning)
const timerStartTime = computed(() => props.task?.timerStartTime)
const timerElapsedTime = computed(() => props.task?.timerElapsedTime || 0)

const formattedTimer = computed(() => {
  const totalSeconds = Math.floor(timerElapsed.value / 1000)
  const hours = Math.floor(totalSeconds / 3600)
  const minutes = Math.floor((totalSeconds % 3600) / 60)
  const seconds = totalSeconds % 60
  return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`
})

const updateTimer = () => {
  if (isTimerRunning.value && timerStartTime.value) {
    timerElapsed.value = Date.now() - timerStartTime.value + timerElapsedTime.value
  } else {
    timerElapsed.value = timerElapsedTime.value
  }
}

// 新增：监听 props.task 的 isTimerRunning、timerStartTime、timerElapsedTime 变化，确保 header 区域按钮和计时器展示实时同步
watch(
  () => [props.task?.isTimerRunning, props.task?.timerStartTime, props.task?.timerElapsedTime],
  () => {
    updateTimer()
  },
)

// 计时器本地状态，保证点击后UI立即切换
const localTimerRunning = ref(false)

// 只要 props.task 变化或全局事件变化，立即同步本地状态
watch(
  () => props.task?.isTimerRunning,
  val => {
    localTimerRunning.value = !!val
    if (!val && timerInterval.value) {
      clearInterval(timerInterval.value)
      timerInterval.value = null
    }
  },
  { immediate: true },
)

// 修正计时器每秒递增逻辑，保证计时器正常跳动
watch(
  [localTimerRunning, timerStartTime, timerElapsedTime],
  () => {
    if (timerInterval.value) {
      clearInterval(timerInterval.value)
      timerInterval.value = null
    }
    if (localTimerRunning.value && timerStartTime.value) {
      updateTimer()
      timerInterval.value = window.setInterval(updateTimer, 1000)
    } else {
      updateTimer()
    }
  },
  { immediate: true },
)

onUnmounted(() => {
  if (timerInterval.value) {
    clearInterval(timerInterval.value)
  }
})

// 根据任务类型确定dialog类型
const dialogType = computed(() => {
  return props.task?.type === 'story' ? 'yes-no-cancel' : 'confirm-cancel'
})

// 根据任务类型确定dialog消息
const dialogMessage = computed(() => {
  if (props.task?.type === 'story') {
    return t.value.confirmDeleteStory.replace('{name}', props.task?.name || '')
  }
  return t.value.confirmDeleteTask.replace('{name}', props.task?.name || '')
})

// 表单数据
const formData = reactive<Task>({
  id: 0, // 默认值，创建时会被重新分配
  name: '',
  type: 'task',
  assignee: '',
  startDate: '',
  endDate: '',
  predecessor: [],
  estimatedHours: 0,
  actualHours: 0,
  progress: 0,
  description: '',
  parentId: undefined, // 上级任务ID
  isTimerRunning: false, // 是否正在计时
  timerStartTime: undefined, // 计时器开始时间
  timerEndTime: undefined, // 计时器结束时间
  timerElapsedTime: 0, // 计时器已用时间
  children: undefined, // 子任务列表
})

// 任务列表数据
const allTasks = ref<Task[]>([])

// 获取可作为上级任务的任务列表（只显示story和task类型，排除当前任务自己）
const availableParentTasks = computed(() => {
  return allTasks.value
    .filter(
      task =>
        task.id !== props.task?.id && // 排除当前任务自己
        (task.type === 'story' || task.type === 'task'), // 只显示story和task类型
    )
    .map(task => ({
      ...task,
      displayName: `${task.name} (${getTaskTypeDisplay(task.type || 'task')})`,
    }))
})

// 获取任务类型的显示文本
const getTaskTypeDisplay = (type: string): string => {
  return (t.value.taskTypeMap as Record<string, string>)?.[type] || type
}

// 计算进度条样式
const progressSliderStyle = computed(() => {
  const progressPercent = formData.progress || 0
  return {
    '--progress-percent': `${progressPercent}%`,
  }
})

// 进度输入框的显示值
const progressDisplayValue = ref('0')

// 处理进度输入
const handleProgressInput = (event: Event) => {
  const target = event.target as HTMLInputElement
  let value = target.value

  // 只保留数字
  value = value.replace(/[^\d]/g, '')

  // 更新输入框显示
  target.value = value
  progressDisplayValue.value = value
}

// 处理进度输入失焦或回车
const handleProgressInputBlur = () => {
  const value = progressDisplayValue.value

  // 转换为数字
  let progress = parseInt(value) || 0

  // 数据验证：小于0或非数字显示0，大于100显示100
  if (progress < 0 || isNaN(progress)) {
    progress = 0
  } else if (progress > 100) {
    progress = 100
  }

  // 更新数据和显示
  formData.progress = progress
  progressDisplayValue.value = progress.toString()
}

// 处理预计工时输入
const handleEstimatedHoursInput = (event: Event) => {
  const target = event.target as HTMLInputElement
  let value = parseFloat(target.value)

  // 数据验证
  if (isNaN(value) || value < 0) {
    value = 0
  } else if (value > 99999) {
    value = 99999
  }

  // 保留两位小数
  formData.estimatedHours = Math.round(value * 100) / 100
}

// 处理实际工时输入
const handleActualHoursInput = (event: Event) => {
  const target = event.target as HTMLInputElement
  let value = parseFloat(target.value)

  // 数据验证
  if (isNaN(value) || value < 0) {
    value = 0
  } else if (value > 99999) {
    value = 99999
  }

  // 保留两位小数
  formData.actualHours = Math.round(value * 100) / 100
}

// 处理进度输入框聚焦（选中全部文本）
const handleProgressInputFocus = (event: Event) => {
  const target = event.target as HTMLInputElement
  // 延迟选中，确保聚焦完成
  setTimeout(() => {
    target.select()
  }, 0)
}

// 处理键盘事件
const handleProgressKeydown = (event: KeyboardEvent) => {
  const key = event.key

  // 允许的按键：数字、退格、删除、方向键、Tab等
  const allowedKeys = [
    'Backspace',
    'Delete',
    'Tab',
    'Escape',
    'Enter',
    'ArrowLeft',
    'ArrowRight',
    'ArrowUp',
    'ArrowDown',
    'Home',
    'End',
    'Control',
    'Meta',
    'Alt',
    'Shift',
  ]

  // 允许数字
  const isNumber = /^\d$/.test(key)
  const isAllowedKey = allowedKeys.includes(key)

  // 如果是Ctrl+A、Ctrl+C、Ctrl+V、Ctrl+X等组合键，允许通过
  if (event.ctrlKey || event.metaKey) {
    return
  }

  // 如果不是允许的按键或数字，阻止输入
  if (!isNumber && !isAllowedKey) {
    event.preventDefault()
  }
}

// 处理小时视图中的日期格式
const processDateForHourView = (dateStr: string | undefined, type: 'start' | 'end'): string => {
  if (!dateStr) return ''

  // 检查是否只有日期部分（YYYY-MM-DD格式）
  if (typeof dateStr === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(dateStr.trim())) {
    // 如果是开始日期，设置为当日00:00
    if (type === 'start') {
      return `${dateStr} 00:00`
    }
    // 如果是结束日期，设置为次日00:00
    if (type === 'end') {
      const date = new Date(dateStr)
      date.setDate(date.getDate() + 1)
      const year = date.getFullYear()
      const month = String(date.getMonth() + 1).padStart(2, '0')
      const day = String(date.getDate()).padStart(2, '0')
      return `${year}-${month}-${day} 00:00`
    }
  }

  // 已经包含时间部分或其他格式，直接返回
  return dateStr
}

// 错误信息
const errors = reactive({
  name: '',
  type: '',
  startDate: '',
  endDate: '',
})

// 监听 visible 属性变化
watch(
  () => props.visible,
  newVal => {
    isVisible.value = newVal
    if (newVal) {
      if (props.task && props.isEdit) {
        // 编辑模式，先重置表单再填充表单数据
        resetForm()
        const taskData = { ...props.task }

        // 处理日期格式：如果是只有日期部分的数据，在小时视图编辑时需要特殊处理
        taskData.startDate = processDateForHourView(taskData.startDate, 'start')
        taskData.endDate = processDateForHourView(taskData.endDate, 'end')

        // 使用 nextTick 确保 resetForm 的响应式更新完成后再赋值
        nextTick(() => {
          Object.assign(formData, taskData)
        })
      } else if (props.task && !props.isEdit) {
        // 新建模式，重置表单
        resetForm()
        // 新建模式，自动绑定上级任务
        formData.parentId = props.task.parentId ?? undefined
        // 新建模式，自动绑定前置任务
        formData.predecessor = props.task.predecessor ?? []
      } else {
        // 没有 task，也重置表单
        resetForm()
      }
      // 抽屉显示时重新请求任务数据，确保前置任务列表是最新的
      window.dispatchEvent(new CustomEvent('request-task-list'))
    }
  },
)

// 监听 isVisible 变化，同步到父组件
watch(isVisible, newVal => {
  emit('update:visible', newVal)
})

// 监听 task 变化，同步更新 parentId
watch(
  () => props.task,
  newTask => {
    if (newTask && !props.isEdit) {
      // 新建时，确保 parentId 与传入的 parentId 同步
      formData.parentId = newTask.parentId ?? undefined
    }
  },
  { immediate: true },
)

// 重置表单
const resetForm = () => {
  Object.assign(formData, {
    name: '',
    type: 'task',
    assignee: '',
    startDate: '',
    endDate: '',
    predecessor: [],
    estimatedHours: 0,
    actualHours: 0,
    progress: 0,
    description: '',
    parentId: undefined,
    isTimerRunning: false,
    timerStartTime: undefined,
    timerEndTime: undefined,
    timerElapsedTime: 0,
    children: undefined,
  })

  // 清除错误信息
  Object.keys(errors).forEach(key => {
    errors[key as keyof typeof errors] = ''
  })
}

// 表单验证
const validateForm = (): boolean => {
  let isValid = true
  Object.keys(errors).forEach(key => {
    errors[key as keyof typeof errors] = ''
  })
  if (!formData.name?.trim()) {
    errors.name = t.value.taskNameRequired
    isValid = false
  } else if (formData.name.length > 50) {
    errors.name = t.value.taskNameTooLong
    isValid = false
  }
  if (!formData.type) {
    errors.type = t.value.taskTypeRequired
    isValid = false
  }
  if (!formData.startDate) {
    errors.startDate = t.value.startDateRequired
    isValid = false
  }
  if (!formData.endDate) {
    errors.endDate = t.value.endDateRequired
    isValid = false
  } else if (formData.startDate && new Date(formData.endDate) < new Date(formData.startDate)) {
    errors.endDate = t.value.endDateInvalid
    isValid = false
  }
  return isValid
}

// 关闭抽屉
const handleClose = () => {
  isVisible.value = false
  emit('close')
}

// 点击遮罩层关闭
const handleOverlayClick = () => {
  handleClose()
}

// 提交表单
const handleSubmit = async () => {
  if (!validateForm()) {
    return
  }
  try {
    submitting.value = true
    const taskData: Task = {
      ...formData,
      id: props.isEdit && props.task ? props.task.id : Date.now(),
    }
    emit('submit', taskData)
    handleClose()
  } catch (error) {
    // 处理错误但不在控制台输出
  } finally {
    submitting.value = false
  }
}

// 删除任务
const handleDelete = () => {
  showDeleteConfirm.value = true
}

const handleError = (error: unknown) => {
  let msg = ''
  if (
    error &&
    typeof error === 'object' &&
    'message' in error &&
    typeof (error as { message?: unknown }).message === 'string'
  ) {
    msg = (error as { message: string }).message
  } else {
    msg = String(error)
  }
  showMessage(msg, 'error', { closable: true })
}

const confirmDelete = () => {
  showDeleteConfirm.value = false
  if (props.task && props.isEdit) {
    try {
      submitting.value = true
      emit('delete', props.task)
      handleClose()
    } catch (error) {
      handleError(error)
    } finally {
      submitting.value = false
    }
  }
}

const cancelDelete = () => {
  showDeleteConfirm.value = false
}

// Story删除：选择"是" - 删除story及其所有子任务
const handleDeleteYes = () => {
  showDeleteConfirm.value = false
  if (props.task && props.isEdit) {
    try {
      submitting.value = true
      emit('delete', props.task, true) // 传递true表示删除所有子任务
      handleClose()
    } catch (error) {
      handleError(error)
    } finally {
      submitting.value = false
    }
  }
}

// Story删除：选择"否" - 仅删除story，保留子任务
const handleDeleteNo = () => {
  showDeleteConfirm.value = false
  if (props.task && props.isEdit) {
    try {
      submitting.value = true
      emit('delete', props.task, false) // 传递false表示仅删除story
      handleClose()
    } catch (error) {
      handleError(error)
    } finally {
      submitting.value = false
    }
  }
}

// 获取任务数据的事件处理器
const handleTasksChanged = (event: CustomEvent) => {
  allTasks.value = event.detail || []
}

// 组件挂载时添加事件监听器
onMounted(() => {
  window.addEventListener('task-list-updated', handleTasksChanged as EventListener)
  // 请求初始任务数据
  window.dispatchEvent(new CustomEvent('request-task-list'))
})

// 组件卸载时移除事件监听器
onUnmounted(() => {
  window.removeEventListener('task-list-updated', handleTasksChanged as EventListener)
})

// 监听 formData.progress 变化，同步更新显示值
watch(
  () => formData.progress,
  newValue => {
    progressDisplayValue.value = (newValue || 0).toString()
  },
  { immediate: true },
)

// 修正计时器首次启动不跳动问题：每次打开抽屉时重置 timerElapsed，且 timerStartTime 为空时立即赋值
watch(
  () => props.visible,
  visible => {
    if (visible && props.task && props.task.type !== 'story') {
      timerElapsed.value = props.task.timerElapsedTime || 0
      // 若计时器未启动，重置本地interval
      if (!props.task.isTimerRunning) {
        if (timerInterval.value) {
          clearInterval(timerInterval.value)
          timerInterval.value = null
        }
      }
    }
  },
  { immediate: true },
)

const handleStartTimer = (desc?: string) => {
  const now = Date.now()
  if (props.task && typeof props.task === 'object') {
    Object.assign(props.task, {
      timerStartTime: now,
      isTimerRunning: true,
      timerElapsedTime: 0, // 每次从0秒开始
      timerStartDesc: desc || '',
    })
    emit('start-timer', props.task)
  }
  timerElapsed.value = 0 // 启动时重置本地计时器
  localTimerRunning.value = true
  updateTimer()
  if (timerInterval.value) {
    clearInterval(timerInterval.value)
    timerInterval.value = null
  }
  window.dispatchEvent(new CustomEvent('start-timer', { detail: props.task }))
}
const handleStopTimer = () => {
  if (props.task && typeof props.task === 'object') {
    emit('stop-timer', props.task)
  }
  localTimerRunning.value = false
  if (timerInterval.value) {
    clearInterval(timerInterval.value)
    timerInterval.value = null
  }
  updateTimer()
  window.dispatchEvent(new CustomEvent('stop-timer', { detail: props.task }))
}

// 计时器确认弹窗
const showTimerConfirm = ref(false)
const timerDesc = ref('')

function openTimerConfirm() {
  timerDesc.value = props.task?.name || ''
  showTimerConfirm.value = true
}
function cancelTimerConfirm() {
  showTimerConfirm.value = false
}
function confirmTimer(desc: string) {
  showTimerConfirm.value = false
  // desc 可用于后续业务
  handleStartTimer(desc)
}

// 处理负责人变更
const handleAssigneeChanged = (event: Event) => {
  const value = (event.target as HTMLSelectElement).value
  // 通过value过滤props.assigneeOptions获取对应的label
  const selected = props.assigneeOptions?.find(option => option.value === value)
  if (selected) {
    // 这里可以根据需要处理选中的负责人信息
    // 例如，可以将负责人名称存储在formData中
    formData.assigneeName = selected.label
  }
}
</script>

<template>
  <div v-if="isVisible" class="drawer-overlay" @click="handleOverlayClick">
    <div class="drawer-container" @click.stop>
      <!-- Drawer Header -->
      <div
        class="drawer-header"
        style="display: flex; align-items: center; justify-content: flex-start; gap: 8px"
      >
        <h3 class="drawer-title" style="margin: 0">{{ isEdit ? t.editTask : t.newTask }}</h3>
        <div
          v-if="props.task?.type !== 'story' && isEdit"
          class="drawer-timer"
          style="display: flex; align-items: center; gap: 6px; margin-left: 8px"
        >
          <button
            v-if="!localTimerRunning"
            class="timer-btn start minimal"
            title="开始计时"
            style="
              width: 24px;
              height: 24px;
              background: #4caf50;
              border: none;
              padding: 0;
              margin: 0;
              box-shadow: none;
              cursor: pointer;
              border-radius: 50%;
              display: flex;
              align-items: center;
              justify-content: center;
              transition: background 0.2s;
            "
            @click.stop="openTimerConfirm"
          >
            <svg
              width="24"
              height="24"
              viewBox="0 0 24 24"
              fill="none"
              style="display: block; margin: 0 auto"
            >
              <circle cx="12" cy="12" r="11" stroke="#4caf50" stroke-width="2" fill="#4caf50" />
              <polygon points="9,7 18,12 9,17" fill="#fff" />
            </svg>
          </button>
          <button
            v-else
            class="timer-btn stop minimal"
            title="停止计时"
            style="
              width: 24px;
              height: 24px;
              background: #f44336;
              border: none;
              padding: 0;
              margin: 0;
              box-shadow: none;
              cursor: pointer;
              border-radius: 50%;
              display: flex;
              align-items: center;
              justify-content: center;
              transition: background 0.2s;
            "
            @click.stop="handleStopTimer"
          >
            <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
              <circle cx="12" cy="12" r="11" stroke="#f44336" stroke-width="2" fill="#f44336" />
              <rect x="7" y="7" width="10" height="10" fill="#fff" rx="1.5" />
            </svg>
          </button>
          <span
            v-if="localTimerRunning"
            class="timer-badge"
            :class="{ 'timer-active': localTimerRunning }"
            style="
              margin-left: 8px;
              font-size: 13px;
              font-weight: 700;
              padding: 2px 10px;
              border-radius: 10px;
              background: #fffbe6;
              color: #e6a23c;
              box-shadow: 0 0 0 1px #ffe58f;
              display: inline-flex;
              align-items: center;
              min-width: 80px;
              justify-content: center;
            "
          >
            <span
              v-if="localTimerRunning"
              class="timer-dot"
              style="
                background: #67c23a;
                width: 7px;
                height: 7px;
                border-radius: 50%;
                margin-right: 5px;
                animation: pulse 1s infinite;
              "
            ></span>
            {{ formattedTimer }}
          </span>
        </div>
        <div style="flex: 1"></div>
        <button class="drawer-close-btn" type="button" @click="handleClose">
          <svg
            class="close-icon"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            style="vertical-align: middle"
          >
            <line x1="18" y1="6" x2="6" y2="18"></line>
            <line x1="6" y1="6" x2="18" y2="18"></line>
          </svg>
        </button>
      </div>

      <!-- Drawer Body -->
      <div class="drawer-body">
        <form class="task-form" @submit.prevent="handleSubmit">
          <div class="form-group">
            <label class="form-label" for="task-name">
              {{ t.taskName }} <span class="required">*</span></label
            >
            <input
              id="task-name"
              v-model="formData.name"
              type="text"
              class="form-input"
              :class="{ error: errors.name }"
              :placeholder="t.taskNamePlaceholder"
            />
            <span v-if="errors.name" class="error-text">{{ errors.name }}</span>
          </div>

          <div class="form-group">
            <label class="form-label" for="task-type">
              {{ t.taskType }} <span class="required">*</span></label
            >
            <select
              id="task-type"
              v-model="formData.type"
              class="form-select"
              :class="{ error: errors.type }"
            >
              <option value="story">{{ t.taskTypeMap.story }}</option>
              <option value="task">{{ t.taskTypeMap.task }}</option>
              <option value="bug">{{ t.taskTypeMap.bug }}</option>
            </select>
            <span v-if="errors.type" class="error-text">{{ errors.type }}</span>
          </div>

          <div class="form-group">
            <label class="form-label" for="task-assignee">{{ t.assignee }}</label>
            <select id="task-assignee" v-model="formData.assignee" class="form-select" @change="handleAssigneeChanged">
              <option value="">{{ t.selectAssignee }}</option>
              <option
                v-for="assignee in props.assigneeOptions"
                :key="assignee.key ?? assignee.value"
                :value="assignee.value"
              >
                {{ assignee.label }}
              </option>
            </select>
          </div>

          <!-- 上级任务选择 -->
          <div class="form-group">
            <label class="form-label" for="task-parent">{{ t.parentTask }}</label>
            <select id="task-parent" v-model="formData.parentId" class="form-select">
              <option :value="undefined">{{ t.noParentTask }}</option>
              <option
                v-for="parentTask in availableParentTasks"
                :key="parentTask.id"
                :value="parentTask.id"
              >
                {{ parentTask.displayName }}
              </option>
            </select>
          </div>

          <div class="form-row">
            <div class="form-group">
              <label class="form-label" for="task-start-date">
                {{ t.startDate }} <span class="required">*</span></label
              >
              <DatePicker
                id="task-start-date"
                v-model="formData.startDate"
                :type="'datetime' as any"
                value-format="YYYY-MM-DD HH:mm"
                :placeholder="t.startDateRequired"
                :class="{ error: errors.startDate }"
              />
              <span v-if="errors.startDate" class="error-text">{{ errors.startDate }}</span>
            </div>

            <div class="form-group">
              <label class="form-label" for="task-end-date">
                {{ t.endDate }} <span class="required">*</span></label
              >
              <DatePicker
                id="task-end-date"
                v-model="formData.endDate"
                :type="'datetime' as any"
                value-format="YYYY-MM-DD HH:mm"
                :placeholder="t.endDateRequired"
                :class="{ error: errors.endDate }"
              />
              <span v-if="errors.endDate" class="error-text">{{ errors.endDate }}</span>
            </div>
          </div>

          <MultiSelectPredecessor
            v-model="formData.predecessor"
            :tasks="allTasks"
            :current-task-id="props.task?.id"
            :label="t.predecessor"
            :placeholder="t.predecessorPlaceholder"
          />

          <div class="form-row">
            <div class="form-group">
              <label class="form-label" for="task-estimated-hours">{{ t.estimatedHours }}</label>
              <input
                id="task-estimated-hours"
                v-model="formData.estimatedHours"
                type="number"
                class="form-input"
                placeholder="0.00"
                min="0"
                max="99999"
                step="0.01"
                @input="handleEstimatedHoursInput"
              />
            </div>

            <div class="form-group">
              <label class="form-label" for="task-actual-hours">{{ t.actualHours }}</label>
              <input
                id="task-actual-hours"
                v-model="formData.actualHours"
                type="number"
                class="form-input"
                placeholder="0.00"
                min="0"
                max="99999"
                step="0.01"
                @input="handleActualHoursInput"
              />
            </div>
          </div>

          <div class="form-group">
            <label class="form-label" for="task-progress">{{ t.progress }}</label>
            <div class="progress-container">
              <input
                id="task-progress"
                v-model.number="formData.progress"
                type="range"
                class="progress-slider"
                :style="progressSliderStyle"
                min="0"
                max="100"
                step="5"
              />
              <div class="progress-input-group">
                <input
                  v-model="progressDisplayValue"
                  type="text"
                  class="progress-input"
                  placeholder="0"
                  maxlength="3"
                  @blur="handleProgressInputBlur"
                  @keyup.enter="handleProgressInputBlur"
                  @input="handleProgressInput"
                  @focus="handleProgressInputFocus"
                  @keydown="handleProgressKeydown"
                />
                <span class="progress-unit">%</span>
              </div>
            </div>
          </div>

          <div class="form-group">
            <label class="form-label" for="task-description">{{ t.description }}</label>
            <textarea
              id="task-description"
              v-model="formData.description"
              class="form-textarea"
              :placeholder="t.descriptionPlaceholder"
              rows="3"
            ></textarea>
          </div>
        </form>
      </div>
      <!-- Drawer Footer -->
      <div class="drawer-footer">
        <div class="footer-left">
          <!-- 删除按钮，仅在编辑模式下显示 -->
          <button
            v-if="isEdit && task"
            type="button"
            class="btn btn-danger"
            :disabled="submitting"
            @click="handleDelete"
          >
            <span v-if="submitting" class="loading-spinner"></span>
            {{ t.delete }}
          </button>
          <GanttConfirmDialog
            :visible="showDeleteConfirm"
            :title="t.delete"
            :type="dialogType"
            :message="dialogMessage"
            :confirm-text="t.confirm"
            :cancel-text="t.cancel"
            :yes-text="t.storyDeleteYes"
            :no-text="t.storyDeleteNo"
            @confirm="confirmDelete"
            @yes="handleDeleteYes"
            @no="handleDeleteNo"
            @cancel="cancelDelete"
          />
        </div>
        <div class="footer-right">
          <button type="button" class="btn btn-default" @click="handleClose">{{ t.cancel }}</button>
          <button
            type="button"
            class="btn btn-primary"
            :disabled="submitting"
            @click="handleSubmit"
          >
            <span v-if="submitting" class="loading-spinner"></span>
            {{ isEdit ? t.update : t.create }}
          </button>
        </div>
      </div>
    </div>
  </div>

  <!-- 计时器确认弹窗 -->
  <ConfirmTimerDialog
    v-if="showTimerConfirm"
    :visible="showTimerConfirm"
    :title="'确认开始计时'"
    :message="`即将为任务${props.task?.name}计时，若有特殊说明请完善下面的描述`"
    :default-desc="props.task?.name || ''"
    @confirm="confirmTimer"
    @cancel="cancelTimerConfirm"
  />
</template>

<style scoped>
@import '../styles/theme-variables.css';

/* 抽屉遮罩层 */
.drawer-overlay {
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 10000; /* 确保在全屏模式下也能正常显示 */
  display: flex;
  justify-content: flex-end;
  align-items: stretch;
}

/* 抽屉容器 */
.drawer-container {
  width: 500px;
  background: var(--gantt-bg-primary, white);
  box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  animation: slideIn 0.3s ease-out;
  color: var(--gantt-text-primary, #303133);
}

@keyframes slideIn {
  from {
    transform: translateX(100%);
  }
  to {
    transform: translateX(0);
  }
}

/* 抽屉头部 */
.drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px;
  border-bottom: 1px solid var(--gantt-border-light, #ebeef5);
  background: var(--gantt-bg-secondary, #f5f7fa);
}

.drawer-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--gantt-text-primary, #303133);
}

.drawer-close-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px;
  color: var(--gantt-text-muted, #909399);
  transition: color 0.2s;
}

.drawer-close-btn:hover {
  color: var(--gantt-text-secondary, #606266);
}

.close-icon {
  width: 16px;
  height: 16px;
  stroke-width: 2;
}

/* 抽屉主体 */
.drawer-body {
  flex: 1;
  padding: 24px;
  overflow-y: auto;
}

/* 表单样式 */
.task-form {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.form-row {
  display: flex;
  gap: 16px;
}

.form-row .form-group {
  flex: 1;
}

.form-label {
  font-size: 14px;
  font-weight: 500;
  color: var(--gantt-text-secondary, #606266);
  line-height: 1.4;
}

.required {
  color: var(--gantt-danger, #f56c6c);
  margin-left: 2px;
}

.form-input,
.form-select,
.form-textarea {
  padding: 12px 16px;
  border: 1px solid var(--gantt-border-medium, #dcdfe6);
  border-radius: 4px;
  font-size: 14px;
  color: var(--gantt-text-primary, #303133); /* 录入后为黑色，与 MilestoneDialog 保持一致 */
  background: var(--gantt-bg-primary, white);
  transition: border-color 0.2s;
  outline: none;
}

.form-input:focus,
.form-select:focus,
.form-textarea:focus {
  border-color: var(--gantt-primary, #409eff);
}

.form-input.error,
.form-select.error {
  border-color: var(--gantt-danger, #f56c6c);
}

.form-input::placeholder,
.form-select::placeholder,
.form-textarea::placeholder {
  color: var(--gantt-text-placeholder, #c0c4cc);
}

.form-textarea {
  resize: vertical;
  min-height: 80px;
}

.error-text {
  color: var(--gantt-danger, #f56c6c);
  font-size: 12px;
  line-height: 1.4;
}

/* 进度条容器 */
.progress-container {
  display: flex;
  align-items: center;
  gap: 12px;
}

.progress-slider {
  flex: 1;
  height: 6px;
  border-radius: 3px;
  background: var(--gantt-border-light, #e4e7ed);
  outline: none;
  appearance: none;
  cursor: pointer;
  position: relative;
  /* 确保input元素本身垂直居中 */
  vertical-align: middle;
}

/* 移除悬停时的高度变化动画，避免抖动 */

/* WebKit 浏览器的已完成部分样式 */
.progress-slider::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(
    to right,
    var(--gantt-primary, #409eff) 0%,
    var(--gantt-primary, #409eff) var(--progress-percent, 0%),
    var(--gantt-border-light, #e4e7ed) var(--progress-percent, 0%),
    var(--gantt-border-light, #e4e7ed) 100%
  );
}

/* Firefox 浏览器的已完成部分样式 */
.progress-slider::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(
    to right,
    var(--gantt-primary, #409eff) 0%,
    var(--gantt-primary, #409eff) var(--progress-percent, 0%),
    var(--gantt-border-light, #e4e7ed) var(--progress-percent, 0%),
    var(--gantt-border-light, #e4e7ed) 100%
  );
  border: none;
}

/* Firefox 需要额外重置，确保轨道居中 */
.progress-slider::-moz-range-progress {
  height: 6px;
  border-radius: 3px;
  background: var(--gantt-primary, #409eff);
}

/* 为更好的兼容性，添加一个伪元素来显示已完成部分 */
.progress-slider::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  height: 6px;
  width: var(--progress-percent, 0%);
  background: var(--gantt-primary, #409eff);
  border-radius: 3px;
  pointer-events: none;
  transition: width 0.2s ease; /* 只保留宽度变化的过渡效果 */
}

/* 移除悬停时的高度变化，避免抖动 */

.progress-slider::-webkit-slider-thumb {
  appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--gantt-primary, #409eff);
  cursor: pointer;
  position: relative;
  z-index: 2;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  transition: box-shadow 0.2s ease; /* 只保留阴影过渡效果 */
  margin-top: -5px; /* 将滑块向上偏移，使其垂直居中 */
}

.progress-slider::-webkit-slider-thumb:hover {
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

.progress-slider::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--gantt-primary, #409eff);
  cursor: pointer;
  border: none;
  position: relative;
  z-index: 2;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  transition: box-shadow 0.2s ease; /* 只保留阴影过渡效果 */
  margin-top: -5px; /* 将滑块向上偏移，使其垂直居中 */
}

.progress-slider::-moz-range-thumb:hover {
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

/* 移除悬停和聚焦状态下的滑块位置调整，保持一致 */

/* 进度输入组样式 */
.progress-input-group {
  display: flex;
  align-items: center;
  border: 1px solid var(--gantt-border-medium, #dcdfe6);
  border-radius: 4px;
  background: var(--gantt-bg-primary, white);
  overflow: hidden;
  transition: border-color 0.2s ease;
  width: 70px; /* 固定宽度，保持紧凑 */
}

.progress-input-group:hover {
  border-color: var(--gantt-primary, #409eff);
}

.progress-input-group:focus-within {
  border-color: var(--gantt-primary, #409eff);
}

/* 进度输入框样式 - 与其他input保持一致 */
.progress-input {
  flex: 1;
  font-size: 14px;
  color: var(--gantt-text-primary, #303133);
  text-align: center;
  border: none;
  outline: none;
  background: transparent;
  padding: 12px 8px; /* 与其他input的padding保持一致 */
  min-width: 0; /* 允许收缩 */
}

.progress-input::placeholder {
  color: var(--gantt-text-placeholder, #c0c4cc);
}

/* 百分号单位样式 */
.progress-unit {
  font-size: 14px;
  color: var(--gantt-text-secondary, #606266);
  padding: 12px 12px 12px 4px; /* 与input的padding匹配 */
  user-select: none;
  flex-shrink: 0; /* 防止%号被压缩 */
}

/* 暗黑模式样式 */
:global(html[data-theme='dark']) .progress-input-group {
  border-color: var(--gantt-border-medium, #4c4d4f);
  background: var(--gantt-bg-primary, #2b2b2b);
}

:global(html[data-theme='dark']) .progress-input-group:hover {
  border-color: var(--gantt-primary, #409eff);
}

:global(html[data-theme='dark']) .progress-input-group:focus-within {
  border-color: var(--gantt-primary, #409eff);
}

:global(html[data-theme='dark']) .progress-input {
  color: var(--gantt-text-primary, #e5eaf3);
  background: transparent;
}

:global(html[data-theme='dark']) .progress-input::placeholder {
  color: var(--gantt-text-placeholder, #8b949e);
}

:global(html[data-theme='dark']) .progress-unit {
  color: var(--gantt-text-secondary, #a8a8a8);
}

/* 抽屉底部 */
.drawer-footer {
  padding: 16px 24px;
  border-top: 1px solid var(--gantt-border-light, #ebeef5);
  background: var(--gantt-bg-toolbar, #fafafa);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.footer-left {
  display: flex;
  align-items: center;
}

.footer-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* 加载动画 */
.loading-spinner {
  width: 12px;
  height: 12px;
  border: 2px solid transparent;
  border-top: 2px solid currentColor;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* 消息提示样式 */
.message {
  animation: messageSlideIn 0.3s ease-out;
}

@keyframes messageSlideIn {
  from {
    transform: translateX(100%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

/* 暗黑模式样式优化 */
:global(html[data-theme='dark']) .drawer-overlay {
  background: rgba(0, 0, 0, 0.7) !important;
}

:global(html[data-theme='dark']) .drawer-container {
  box-shadow: -4px 0 15px rgba(0, 0, 0, 0.4) !important;
}

:global(html[data-theme='dark']) .drawer-close-btn:hover {
  background: var(--gantt-bg-hover, rgba(255, 255, 255, 0.1)) !important;
  border-radius: 4px;
}

:global(html[data-theme='dark']) .form-input:focus,
:global(html[data-theme='dark']) .form-select:focus,
:global(html[data-theme='dark']) .form-textarea:focus {
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2) !important;
}

:global(html[data-theme='dark']) .form-input::placeholder,
:global(html[data-theme='dark']) .form-textarea::placeholder {
  color: var(--gantt-text-muted, #9e9e9e) !important;
}
</style>
