<template>
  <div class="schedule-preview-wrap">
    <div class="gantt-main-area">
      <div ref="ganttContainerRef" class="schedule-gantt-container" :style="{ height }"></div>
    </div>
    <div class="schedule-detail-panel">
      <div class="schedule-detail-title">计划信息</div>
      <template v-if="activePreviewDevice">
        <el-descriptions :column="1" border size="small">
          <el-descriptions-item label="设备名称">{{ activePreviewDevice.deviceName }}</el-descriptions-item>
          <el-descriptions-item label="设备ID">{{ activePreviewDevice.deviceId }}</el-descriptions-item>
          <el-descriptions-item v-if="activePreviewDevice.capacityType !== undefined" label="产能来源">{{ getCapacityTypeLabel(activePreviewDevice.capacityType) }}</el-descriptions-item>
          <el-descriptions-item v-if="activePreviewDevice.capacityType === 1" label="产能">{{ activePreviewDevice.ratedCapacity ?? '-' }}</el-descriptions-item>
          <el-descriptions-item v-if="'dailyAverageValue' in activePreviewDevice" label="每日报工平均值">{{ activePreviewDevice.dailyAverageValue ?? '-' }}</el-descriptions-item>
          <el-descriptions-item v-if="'dataCollectionCapacity' in activePreviewDevice" label="数据采集产能">{{ activePreviewDevice.dataCollectionCapacity ?? '-' }}</el-descriptions-item>
          <el-descriptions-item label="计划条数">{{ activePreviewDevice.plans?.length ?? 0 }}</el-descriptions-item>
        </el-descriptions>
        <div class="schedule-plan-list-title">计划明细</div>
        <div class="schedule-plan-list">
          <div
            v-for="(plan, index) in activePreviewTask ? [activePreviewTask] : (activePreviewDevice?.plans ?? [])"
            :key="`${activePreviewDevice?.deviceId}-${plan.planId}-${index}`"
            :class="['schedule-plan-item', { 'schedule-plan-item-active': plan.sourceType === 'CURRENT' }]"
          >
            <div class="schedule-plan-item-head">
              <span class="schedule-plan-item-title">{{ plan.productCode ?? '-' }} / {{ plan.productName ?? '-' }}</span>
            </div>
            <div>计划编码：{{ plan.taskCode ?? '-' }}</div>
            <div>计划数量：{{ plan.planNumber ?? '-' }}</div> 
            <template v-if="activePreviewDevice.capacityType !== 1">
              <div>产能：{{ plan.ratedCapacity ?? '-' }}</div>
              <div>产能来源：{{ getCapacityTypeLabel(plan.capacityType) }}</div>
            </template>
            <div>交货日期：{{ plan.deliveryDateStr ?? '-' }}</div>
            <div>开始：{{ plan.planStartTimeStr || '-' }}</div>
            <div>结束：{{ plan.planEndTimeStr || '-' }}</div>
            <div>最晚开工：{{ plan.latestStartTimeStr || '-' }}</div>
           
          </div>
        </div>
      </template>
      <el-empty v-else description="暂无计划信息" :image-size="80" />
    </div>
  </div>

  <el-dialog v-model="taskAdjustDialogVisible" title="调整任务" width="420px" append-to-body>
    <el-form label-width="110px">
      <el-form-item label="设备">
        <el-select v-model="taskAdjustForm.deviceTaskId" placeholder="请选择设备" class="!w-full">
          <el-option v-for="item in previewDeviceOptions" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>
      <el-form-item label="计划开始日期">
        <el-date-picker
          v-model="taskAdjustForm.startDate"
          type="datetime"
          value-format="YYYY-MM-DD HH:mm:ss"
          placeholder="请选择计划开始日期"
          class="!w-full"
        />
      </el-form-item>
      <el-form-item label="计划结束日期">
        <el-date-picker
          v-model="taskAdjustForm.endDate"
          type="datetime"
          value-format="YYYY-MM-DD HH:mm:ss"
          placeholder="请选择计划结束日期"
          class="!w-full"
        />
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="taskAdjustDialogVisible = false">取消</el-button>
      <el-button type="primary" @click="handleTaskAdjustSubmit">确定</el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import dayjs from 'dayjs'
import { gantt } from 'dhtmlx-gantt'
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
import { getDictOptions } from '@/utils/dict'

defineOptions({ name: 'ScheduleGanttPanelEditable' })

const props = withDefaults(
  defineProps<{
    scheduleList: any[]
    height?: string
  }>(),
  {
    height: '800px'
  }
)

const message = useMessage()
const ganttContainerRef = ref<HTMLDivElement>()
const activePreviewDevice = ref<any>()
const activePreviewTask = ref<any>()
const ganttEventIds = ref<string[]>([])
const ganttSyncing = ref(false)
const taskAdjustDialogVisible = ref(false)
const taskAdjustForm = reactive({
  deviceTaskId: '',
  startDate: '',
  endDate: ''
})
const editingPlanIdentity = ref<string | null>(null)

const getCapacityTypeLabel = (value: any) => {
  if (value === undefined || value === null) return '-'
  const options = getDictOptions('capacity_sources')
  const found = options.find((opt) => Number(opt.value) === Number(value))
  return found?.label ?? String(value)
}

const previewScheduleList = computed(() => (Array.isArray(props.scheduleList) ? props.scheduleList : []))
const previewDeviceOptions = computed(() =>
  previewScheduleList.value.map((device: any) => ({
    label: device?.deviceName ?? '-',
    value: `device-${device?.deviceId}`
  }))
)

const hasCurrentPlan = (device: any) =>
  (device?.plans ?? []).some((plan: any) => String(plan.sourceType ?? '').toUpperCase() === 'CURRENT')

const getGanttScheduleList = () =>
  previewScheduleList.value.filter((device: any) => hasCurrentPlan(device))

const getGlobalDateRange = (scheduleList: any[]) => {
  const allPlans = scheduleList.flatMap((item: any) => item?.plans ?? [])
  const starts = allPlans.map((item: any) => dayjs(item?.planStartTimeStr).valueOf()).filter((item: number) => Number.isFinite(item))
  const ends = allPlans.map((item: any) => dayjs(item?.planEndTimeStr).valueOf()).filter((item: number) => Number.isFinite(item))
  if (!starts.length || !ends.length) {
    const now = Date.now()
    return { start: now, end: now + 7 * 24 * 60 * 60 * 1000 }
  }
  return { start: Math.min(...starts), end: Math.max(...ends) }
}

const formatGanttDate = (value: unknown) => {
  const date = dayjs(value)
  if (!date.isValid()) return undefined
  return date.format('YYYY-MM-DD HH:mm')
}

const buildPreviewGanttData = (scheduleList: any[]) => {
  const tasks: any[] = []

  scheduleList.forEach((device: any) => {
    const plans = (device?.plans ?? []).map((plan: any) => ({
      ...plan,
      _start: dayjs(plan?.planStartTimeStr),
      _end: dayjs(plan?.planEndTimeStr)
    }))
    const validPlans = plans
      .filter((plan: any) => plan._start.isValid() && plan._end.isValid())
      .sort((a: any, b: any) => a._start.valueOf() - b._start.valueOf())

    if (!validPlans.length) return

    const allStarts = validPlans.map((p: any) => p._start.valueOf())
    const allEnds = validPlans.map((p: any) => p._end.valueOf())
    const earliestStart = dayjs(Math.min(...allStarts))
    const latestEnd = dayjs(Math.max(...allEnds))
    const totalDays = Math.max(latestEnd.endOf('day').diff(earliestStart.startOf('day'), 'day') + 1, 1)

    tasks.push({
      id: `device-${device.deviceId}`,
      text: device.deviceName ?? '-',
      start_date: formatGanttDate(earliestStart),
      end_date: formatGanttDate(latestEnd),
      duration: totalDays,
      parent: 0,
      progress: 0,
      readonly: true,
      deviceName: device.deviceName ?? '-',
      totalDays,
      _deviceData: device,
      _validPlans: validPlans
    })
  })

  return { data: tasks, links: [] }
}

const destroyGantt = () => {
  ganttEventIds.value.forEach((eventId) => {
    try { gantt.detachEvent(eventId) } catch {}
  })
  ganttEventIds.value = []
  try { gantt.clearAll() } catch {}
}

const formatTooltipDateTime = (value: unknown) => {
  const date = dayjs(value)
  if (!date.isValid()) return '-'
  return date.format('YYYY-MM-DD HH:mm:ss')
}

const clearCustomPlanBars = () => {
  if (!ganttContainerRef.value) return
  const existing = ganttContainerRef.value.querySelectorAll('.custom-plan-bar')
  existing.forEach((el) => el.remove())
}

const buildPlanBarTooltipHtml = (plan: any, device: any) => {
  return `
    <div><b>任务明细</b></div>
    <div>设备：${device?.deviceName ?? '-'}</div>
    <div>任务单：${plan.taskCode ?? '-'}</div>
    <div>产品：${plan.productCode ?? '-'} / ${plan.productName ?? '-'}</div>
    <div>计划数量：${plan.planNumber ?? '-'}</div>
    <div>开始：${formatTooltipDateTime(plan.planStartTimeStr)}</div>
    <div>结束：${formatTooltipDateTime(plan.planEndTimeStr)}</div>
    <div>最晚开工：${formatTooltipDateTime(plan.latestStartTimeStr)}</div>
  `
}

const makePlanIdentity = (plan: any) =>
  `${plan?.taskId ?? ''}-${plan?.taskDetailId ?? ''}-${plan?.planId ?? ''}`

const updatePlanTime = (plan: any, newStart: dayjs.Dayjs, newEnd: dayjs.Dayjs) => {
  plan.planStartTimeStr = newStart.format('YYYY-MM-DD HH:mm:ss')
  plan.planEndTimeStr = newEnd.format('YYYY-MM-DD HH:mm:ss')
  plan.planStartTime = newStart.valueOf()
  plan.planEndTime = newEnd.valueOf()
  plan.scheduleDays = Math.max(newEnd.diff(newStart, 'day') + 1, 1)
}

const movePlanToDevice = (plan: any, sourceDevice: any, targetDevice: any) => {
  if (sourceDevice?.deviceId === targetDevice?.deviceId) return
  const identity = makePlanIdentity(plan)
  if (sourceDevice?.plans && Array.isArray(sourceDevice.plans)) {
    sourceDevice.plans = sourceDevice.plans.filter((item: any) => makePlanIdentity(item) !== identity)
  }
  if (!Array.isArray(targetDevice.plans)) {
    targetDevice.plans = []
  }
  const exists = targetDevice.plans.some((item: any) => makePlanIdentity(item) === identity)
  if (!exists) {
    targetDevice.plans.push(plan)
  }
  plan.deviceId = targetDevice.deviceId
  plan.feedingPipeline = targetDevice.deviceId
}

const renderCustomPlanBars = () => {
  clearCustomPlanBars()
  if (!ganttContainerRef.value) return

  const taskRows = ganttContainerRef.value.querySelectorAll('.gantt_task_row')
  taskRows.forEach((row: Element) => {
    const taskId = row.getAttribute('task_id')
    if (!taskId) return
    const task = gantt.getTask(taskId)
    if (!task?._validPlans) return

    const plans = task._validPlans as any[]
    const rowHeight = gantt.config.row_height
    const barHeight = Math.min(gantt.config.bar_height, rowHeight - 8)
    const barTop = (rowHeight - barHeight) / 2

    plans.forEach((plan: any) => {
      const planStart = dayjs(plan.planStartTimeStr)
      const planEnd = dayjs(plan.planEndTimeStr)
      if (!planStart.isValid() || !planEnd.isValid()) return

      const leftPos = gantt.posFromDate(planStart.toDate())
      const rightPos = gantt.posFromDate(planEnd.toDate())
      const width = Math.max(rightPos - leftPos, 4)
      const isCurrent = String(plan.sourceType ?? '').toUpperCase() === 'CURRENT'

      const bar = document.createElement('div')
      bar.className = 'custom-plan-bar'
      if (isCurrent) {
        bar.classList.add('custom-plan-bar-current')
      }
      bar.style.cssText = `
        position: absolute;
        left: ${leftPos}px;
        top: ${barTop}px;
        width: ${width}px;
        height: ${barHeight}px;
        border-radius: 6px;
        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        cursor: ${isCurrent ? 'grab' : 'pointer'};
        z-index: 2;
        display: flex;
        align-items: center;
        padding: 0 8px;
        font-size: 12px;
        font-weight: 500;
        color: #ffffff;
        text-shadow: 0 1px 2px rgba(0,0,0,0.1);
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
        box-sizing: border-box;
      `

      if (isCurrent) {
        bar.style.backgroundColor = '#67c23a'
      } else {
        const planStatus = plan.planStatus
        const statusColors: Record<number, string> = {
          1: '#3b82f6',
          8: '#10b981',
          3: '#f59e0b',
          4: '#f56c6c',
          5: '#8e7cc3'
        }
        bar.style.backgroundColor = statusColors[planStatus] || '#6b7280'
      }

      bar.textContent = `${plan.productCode ?? '-'} / ${plan.productName ?? '-'}`

      bar.setAttribute('data-plan-id', String(plan.planId ?? ''))
      bar.setAttribute('data-device-id', String(task._deviceData?.deviceId ?? ''))

      bar.addEventListener('click', (e) => {
        e.stopPropagation()
        activePreviewTask.value = plan
        activePreviewDevice.value = task._deviceData
      })

      bar.addEventListener('mouseenter', (e) => {
        const tooltipsExt = (gantt.ext as any)?.tooltips
        const tooltip = tooltipsExt?.tooltip
        if (!tooltip) return
        const html = buildPlanBarTooltipHtml(plan, task._deviceData)
        tooltip.setContent(html)
        tooltip.show(e)
        const node = tooltip.getNode?.()
        if (node) {
          node.style.display = 'block'
          node.style.visibility = 'visible'
          node.style.opacity = '1'
          node.style.zIndex = '10000'
          node.style.pointerEvents = 'none'
        }
      })

      bar.addEventListener('mouseleave', () => {
        const tooltipsExt = (gantt.ext as any)?.tooltips
        const tooltip = tooltipsExt?.tooltip
        if (tooltip) { tooltip.hide() }
      })

      bar.addEventListener('contextmenu', (e) => {
        if (!isCurrent) { e.preventDefault(); return }
        e.preventDefault()
        openTaskAdjustDialogForPlan(plan, task._deviceData)
      })

      if (isCurrent) {
        attachPlanBarDrag(bar, plan, task)
        attachPlanBarResize(bar, plan, task)
      }

      row.appendChild(bar)
    })
  })
}

const findOriginalPlan = (planIdentity: string) => {
  for (const device of previewScheduleList.value) {
    const plan = (device?.plans ?? []).find(
      (p: any) => makePlanIdentity(p) === planIdentity
    )
    if (plan) return { plan, device }
  }
  return null
}

const attachPlanBarDrag = (bar: HTMLElement, plan: any, task: any) => {
  let startX = 0
  let startLeft = 0
  let dragging = false
  let moved = false

  const onMouseDown = (e: MouseEvent) => {
    if (e.button !== 0) return
    const target = e.target as HTMLElement
    if (target.classList.contains('custom-plan-resize-handle')) return
    e.preventDefault()
    e.stopPropagation()
    startX = e.clientX
    startLeft = bar.offsetLeft
    dragging = true
    moved = false
    bar.style.cursor = 'grabbing'
    bar.style.zIndex = '10'
    bar.style.opacity = '0.85'
    document.addEventListener('mousemove', onMouseMove)
    document.addEventListener('mouseup', onMouseUp)
  }

  const onMouseMove = (e: MouseEvent) => {
    if (!dragging) return
    const dx = e.clientX - startX
    if (Math.abs(dx) < 3 && !moved) return
    moved = true
    const newLeft = Math.max(0, startLeft + dx)
    bar.style.left = `${newLeft}px`
  }

  const onMouseUp = (e: MouseEvent) => {
    document.removeEventListener('mousemove', onMouseMove)
    document.removeEventListener('mouseup', onMouseUp)
    dragging = false
    bar.style.cursor = 'grab'
    bar.style.zIndex = '2'
    bar.style.opacity = '1'

    if (!moved) return
    moved = false

    const dx = e.clientX - startX
    const newLeft = Math.max(0, startLeft + dx)
    const newStartDate = gantt.dateFromPos(newLeft)
    const planDuration = dayjs(plan.planEndTimeStr).diff(dayjs(plan.planStartTimeStr), 'millisecond')
    const newEndDate = new Date(newStartDate.getTime() + planDuration)

    const newStart = dayjs(newStartDate)
    const newEnd = dayjs(newEndDate)

    const identity = makePlanIdentity(plan)
    const original = findOriginalPlan(identity)
    if (original) {
      updatePlanTime(original.plan, newStart, newEnd)
    } else {
      updatePlanTime(plan, newStart, newEnd)
    }

    const targetDeviceEl = findDeviceRowAtPosition(bar, newLeft)
    if (targetDeviceEl) {
      const targetDeviceId = targetDeviceEl.getAttribute('data-device-id')
      const targetDevice = previewScheduleList.value.find((d: any) => String(d.deviceId) === targetDeviceId)
      if (targetDevice && targetDevice.deviceId !== task._deviceData?.deviceId) {
        const sourceDevice = original?.device ?? task._deviceData
        movePlanToDevice(original?.plan ?? plan, sourceDevice, targetDevice)
      }
    }

    editingPlanIdentity.value = identity
    initGanttPreview()
  }

  bar.addEventListener('mousedown', onMouseDown)
}

const findDeviceRowAtPosition = (bar: HTMLElement, left: number) => {
  const barRect = bar.getBoundingClientRect()
  const centerY = barRect.top + barRect.height / 2
  const centerX = barRect.left + left + barRect.width / 2
  const elAtCenter = document.elementFromPoint(centerX, centerY)
  if (!elAtCenter) return null
  const row = elAtCenter.closest('.gantt_task_row') as HTMLElement
  if (!row) return null
  const taskId = row.getAttribute('task_id')
  if (!taskId) return null
  const ganttTask = gantt.getTask(taskId)
  if (!ganttTask?._deviceData) return null
  return { getAttribute: (attr: string) => String(ganttTask._deviceData.deviceId ?? '') }
}

const attachPlanBarResize = (bar: HTMLElement, plan: any, task: any) => {
  const leftHandle = document.createElement('div')
  leftHandle.className = 'custom-plan-resize-handle custom-plan-resize-left'
  leftHandle.style.cssText = `
    position: absolute; left: 0; top: 0; width: 8px; height: 100%;
    cursor: w-resize; z-index: 3;
  `
  const rightHandle = document.createElement('div')
  rightHandle.className = 'custom-plan-resize-handle custom-plan-resize-right'
  rightHandle.style.cssText = `
    position: absolute; right: 0; top: 0; width: 8px; height: 100%;
    cursor: e-resize; z-index: 3;
  `
  bar.appendChild(leftHandle)
  bar.appendChild(rightHandle)

  const attachResize = (handle: HTMLElement, isLeft: boolean) => {
    let startX = 0
    let startLeft = 0
    let startWidth = 0
    let resizing = false

    const onMouseDown = (e: MouseEvent) => {
      e.preventDefault()
      e.stopPropagation()
      startX = e.clientX
      startLeft = bar.offsetLeft
      startWidth = bar.offsetWidth
      resizing = true
      bar.style.zIndex = '10'
      document.addEventListener('mousemove', onMouseMove)
      document.addEventListener('mouseup', onMouseUp)
    }

    const onMouseMove = (e: MouseEvent) => {
      if (!resizing) return
      const dx = e.clientX - startX
      if (isLeft) {
        const newLeft = Math.max(0, startLeft + dx)
        const newWidth = Math.max(20, startWidth - dx)
        bar.style.left = `${newLeft}px`
        bar.style.width = `${newWidth}px`
      } else {
        const newWidth = Math.max(20, startWidth + dx)
        bar.style.width = `${newWidth}px`
      }
    }

    const onMouseUp = () => {
      document.removeEventListener('mousemove', onMouseMove)
      document.removeEventListener('mouseup', onMouseUp)
      if (!resizing) return
      resizing = false
      bar.style.zIndex = '2'

      const newLeft = parseFloat(bar.style.left) || startLeft
      const newWidth = parseFloat(bar.style.width) || startWidth
      const newStartDate = gantt.dateFromPos(newLeft)
      const newEndDate = gantt.dateFromPos(newLeft + newWidth)

      const identity = makePlanIdentity(plan)
      const original = findOriginalPlan(identity)
      if (original) {
        updatePlanTime(original.plan, dayjs(newStartDate), dayjs(newEndDate))
      } else {
        updatePlanTime(plan, dayjs(newStartDate), dayjs(newEndDate))
      }
      editingPlanIdentity.value = identity
      initGanttPreview()
    }

    handle.addEventListener('mousedown', onMouseDown)
  }

  attachResize(leftHandle, true)
  attachResize(rightHandle, false)
}

const openTaskAdjustDialogForPlan = (plan: any, device: any) => {
  taskAdjustForm.deviceTaskId = `device-${device?.deviceId ?? ''}`
  taskAdjustForm.startDate = plan.planStartTimeStr || ''
  taskAdjustForm.endDate = plan.planEndTimeStr || ''
  editingPlanIdentity.value = makePlanIdentity(plan)
  taskAdjustDialogVisible.value = true
}

const handleTaskAdjustSubmit = () => {
  if (!taskAdjustForm.deviceTaskId || !taskAdjustForm.startDate || !taskAdjustForm.endDate) {
    message.warning('请完善设备、计划开始日期和计划结束日期')
    return
  }
  if (!editingPlanIdentity.value) return

  const targetDevice = previewScheduleList.value.find(
    (d: any) => `device-${d.deviceId}` === taskAdjustForm.deviceTaskId
  )
  if (!targetDevice) return

  let foundPlan: any = null
  let sourceDevice: any = null
  for (const device of previewScheduleList.value) {
    const plan = (device?.plans ?? []).find(
      (p: any) => makePlanIdentity(p) === editingPlanIdentity.value
    )
    if (plan) {
      foundPlan = plan
      sourceDevice = device
      break
    }
  }
  if (!foundPlan) return

  const newStart = dayjs(taskAdjustForm.startDate)
  const newEnd = dayjs(taskAdjustForm.endDate)
  if (!newStart.isValid() || !newEnd.isValid()) {
    message.warning('请选择有效的时间')
    return
  }
  if (newEnd.isBefore(newStart)) {
    message.warning('结束时间不能早于开始时间')
    return
  }

  updatePlanTime(foundPlan, newStart, newEnd)
  if (sourceDevice?.deviceId !== targetDevice.deviceId) {
    movePlanToDevice(foundPlan, sourceDevice, targetDevice)
  }

  taskAdjustDialogVisible.value = false
  editingPlanIdentity.value = makePlanIdentity(foundPlan)
  initGanttPreview()
}

const initGanttPreview = () => {
  if (!ganttContainerRef.value) return
  destroyGantt()
  clearCustomPlanBars()

  const ganttScheduleData = getGanttScheduleList()
  if (!ganttScheduleData.length) {
    activePreviewDevice.value = undefined
    activePreviewTask.value = undefined
    return
  }

  gantt.plugins({ tooltip: true })

  gantt.config.tooltip_timeout = 0
  gantt.templates.tooltip_text = () => ''

  gantt.config.readonly = true
  gantt.config.drag_move = false
  gantt.config.drag_links = false
  gantt.config.drag_progress = false
  gantt.config.drag_resize = false
  gantt.config.order_branch = false
  gantt.config.order_branch_free = false
  gantt.config.details_on_dblclick = false
  gantt.config.show_progress = false

  gantt.config.row_height = 48
  gantt.config.scale_height = 70
  gantt.config.xml_date = '%Y-%m-%d %H:%i'
  gantt.config.task_height = 36
  gantt.config.min_column_width = 80
  gantt.config.column_width = 90
  gantt.config.bar_height = 34
  gantt.config.resize_step = 15

  gantt.config.columns = [
    {
      name: 'text',
      label: '设备名称',
      tree: false,
      width: '*',
      min_width: 100,
      template: (task: any) => task.deviceName ?? task.text ?? '-'
    },
    {
      name: 'duration',
      label: '天数',
      align: 'center',
      width: 80,
      template: (task: any) => String(task.totalDays ?? task.duration ?? 0)
    }
  ]

  gantt.config.scales = [
    { unit: 'month', step: 1, format: (date) => dayjs(date).format('YYYY年M月') },
    { unit: 'day', step: 1, format: (date) => dayjs(date).format('MM-DD') }
  ]

  gantt.templates.task_class = (_start, _end, task: any) => {
    if (task._validPlans) return 'schedule-device-row'
    return ''
  }

  const globalRange = getGlobalDateRange(ganttScheduleData)
  gantt.config.start_date = dayjs(globalRange.start).startOf('day').toDate()
  gantt.config.end_date = dayjs(globalRange.end).endOf('day').toDate()

  gantt.init(ganttContainerRef.value)

  const ganttData = buildPreviewGanttData(ganttScheduleData)
  gantt.parse(ganttData)

  if (ganttData.data.length) {
    const restoreDevice = editingPlanIdentity.value
      ? ganttScheduleData.find((d: any) =>
          (d?.plans ?? []).some((p: any) => makePlanIdentity(p) === editingPlanIdentity.value)
        )
      : null
    activePreviewDevice.value = restoreDevice || ganttData.data[0]._deviceData
    const today = dayjs().startOf('day').toDate()
    const pos = gantt.posFromDate(today)
    const scrollState = gantt.getScrollState()
    if (scrollState && pos >= 0) {
      const halfWidth = scrollState.inner_width / 3
      gantt.scrollTo(Math.max(0, pos - halfWidth), 0)
    } else {
      gantt.showDate(today)
    }
  }

  const clickEventId = gantt.attachEvent('onTaskClick', (id) => {
    const ganttTask = gantt.getTask(id)
    if (ganttTask?._deviceData) {
      activePreviewTask.value = undefined
      activePreviewDevice.value = ganttTask._deviceData
    }
    nextTick(() => {
      renderCustomPlanBars()
    })
    return true
  })
  ganttEventIds.value.push(clickEventId)

  nextTick(() => {
    renderCustomPlanBars()
  })

  const renderEventId = gantt.attachEvent('onGanttRender', () => {
    nextTick(() => {
      renderCustomPlanBars()
    })
  })
  ganttEventIds.value.push(renderEventId)
}

onMounted(async () => {
  await nextTick()
  initGanttPreview()
})

watch(
  () => props.scheduleList,
  async () => {
    if (ganttSyncing.value) return
    await nextTick()
    if (ganttSyncing.value) return
    initGanttPreview()
  },
  { deep: true }
)

onBeforeUnmount(() => {
  destroyGantt()
})
</script>

<style scoped>
.schedule-preview-wrap {
  display: flex;
  width: 100%;
  height: 100%;
  gap: 12px;
  overflow: hidden;
}

.gantt-main-area {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.schedule-gantt-container {
  min-width: 0;
  border: 1px solid var(--el-border-color);
  border-radius: 4px;
  overflow: hidden;
}

.schedule-detail-panel {
  width: 280px;
  flex: 0 0 280px;
}

.schedule-detail-title {
  margin-bottom: 10px;
  font-weight: 600;
}

.schedule-plan-list-title {
  margin-top: 14px;
  margin-bottom: 10px;
  font-weight: 600;
}

.schedule-plan-list {
  overflow: auto;
  max-height: 55vh;
  border: 1px solid var(--el-border-color);
  border-radius: 4px;
  padding: 8px;
}

.schedule-plan-item {
  padding: 8px;
  border-radius: 4px;
  background: var(--el-fill-color-light);
}

.schedule-plan-item-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 4px;
}

.schedule-plan-item-title {
  font-weight: 600;
  color: var(--el-text-color-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.schedule-plan-item-active {
  border: 1px solid var(--el-color-success-light-5);
  background: var(--el-color-success-light-9);
}

.schedule-plan-item + .schedule-plan-item {
  margin-top: 8px;
}

.schedule-gantt-container :deep(.gantt_task_line.schedule-device-row) {
  visibility: hidden;
  pointer-events: none;
}

.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task) {
  background: #67c23a;
}

.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task .gantt_task_content) {
  color: #ffffff;
}

.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-history) {
  background: #9ca3af;
  opacity: 0.7;
}

.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-history .gantt_task_content) {
  color: #ffffff;
}

:deep(.gantt_tooltip) {
  z-index: 5000 !important;
  background: rgba(255, 255, 255, 0.95) !important;
  border: 1px solid #e5e7eb !important;
  border-radius: 8px !important;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06) !important;
  padding: 12px !important;
  font-size: 13px !important;
  line-height: 1.5 !important;
}

:deep(.gantt_tooltip) div {
  margin-bottom: 4px;
}

:deep(.gantt_tooltip) div:last-child {
  margin-bottom: 0;
}

:deep(.gantt_tooltip) b {
  font-size: 14px;
  color: var(--el-text-color-primary);
}
</style>
