<template>
  <div class="video-timeline-editor">
    <!-- 顶部工具栏 -->
    <div class="editor-toolbar">
      <div class="toolbar-left">
        <el-button-group>
          <el-button :icon="VideoPlay" @click="playTimeline" :disabled="timelineClips.length === 0">{{ $t('common.play') }}</el-button>
          <el-button :icon="VideoPause" @click="pauseTimeline">{{ $t('common.pause') }}</el-button>
        </el-button-group>
        <span class="time-display">{{ formatTime(currentTime) }} / {{ formatTime(totalDuration) }}</span>
      </div>
      <div class="toolbar-right">
        <el-button 
          type="primary" 
          :icon="VideoCamera"
          @click="submitTimelineForMerge"
          :disabled="timelineClips.length === 0"
          :loading="serverMerging"
        >
          {{ $t('video.merge') }}
        </el-button>
      </div>
    </div>

    <!-- 主工作区 -->
    <div class="editor-workspace">
      <!-- 预览区域 -->
      <div class="preview-panel">
        <div class="video-preview" @click="togglePlay">
          <video 
            ref="previewPlayer"
            :src="currentPreviewUrl"
            @loadedmetadata="handlePreviewLoaded"
            @timeupdate="handlePreviewTimeUpdate"
            @ended="handlePreviewEnded"
          />
          <!-- 音频播放器（隐藏） -->
          <audio 
            ref="audioPlayer"
            :src="currentAudioUrl"
            @loadedmetadata="handleAudioLoaded"
            @ended="handleAudioEnded"
            style="display: none;"
          />
          <!-- 转场效果层 -->
          <div 
            v-if="transitionState.active"
            class="transition-overlay"
            :class="[`transition-${transitionState.type}`, { 'transition-in': transitionState.phase === 'in', 'transition-out': transitionState.phase === 'out' }]"
            :style="{ animationDuration: transitionState.duration + 's' }"
          ></div>
          <!-- 播放/暂停图标覆盖层 -->
          <div class="video-play-overlay" :class="{ hidden: isPlaying }" v-if="currentPreviewUrl">
            <el-icon :size="64"><VideoPlay /></el-icon>
          </div>
          <div class="preview-overlay" v-if="!currentPreviewUrl">
            <el-empty :description="$t('video.dragToTimeline')" />
          </div>
        </div>
        <div class="preview-controls">
          <el-slider 
            v-model="currentTime" 
            :max="totalDuration"
            :step="0.1"
            @change="seekToTime"
          />
        </div>
      </div>

      <!-- 素材库 -->
      <div class="media-library">
        <div class="library-header">
          <div class="header-left">
            <h4>{{ $t('video.mediaLibrary') }}</h4>
            <span>{{ $t('video.videoCount', { count: availableStoryboards.length }) }}</span>
          </div>
          <el-button 
            type="primary" 
            size="small"
            :icon="FolderAdd"
            @click="addAllScenesInOrder"
            :disabled="availableStoryboards.length === 0"
          >
            {{ $t('common.addAll') }}
          </el-button>
        </div>
        <div class="media-grid">
          <div
            v-for="scene in availableStoryboards"
            :key="scene.id"
            class="media-item"
            draggable="true"
            @dragstart="handleDragStart($event, scene)"
          >
            <div class="media-thumbnail" @click="previewScene(scene)">
              <video :src="scene.video_url" />
              <div class="media-duration">{{ scene.duration > 0 ? scene.duration.toFixed(1) : '?' }}s</div>
              <el-button 
                class="delete-btn"
                type="danger" 
                size="small" 
                :icon="Delete"
                circle
                @click.stop="deleteAsset(scene)"
              />
              <div class="media-overlay">
                <el-button 
                  type="primary" 
                  size="small" 
                  :icon="Plus"
                  @click.stop="addClipToTimeline(scene)"
                >
                  {{ $t('common.addToTimeline') }}
                </el-button>
              </div>
            </div>
            <div class="media-info">
              <div class="media-title">{{ $t('storyboard.shot') }} #{{ scene.storyboard_num || scene.assetId }}</div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 时间线区域 -->
    <div class="timeline-panel">
      <div class="timeline-header">
        <div class="zoom-controls">
          <el-button-group size="small">
            <el-button @click="zoomOut">-</el-button>
            <el-button @click="zoomReset">{{ $t('common.reset') }}</el-button>
            <el-button @click="zoomIn">+</el-button>
          </el-button-group>
          <span class="zoom-level">{{ Math.round(zoom * 100) }}%</span>
        </div>
      </div>

      <div class="timeline-container" ref="timelineContainer">
        <!-- 时间标尺 -->
        <div class="timeline-ruler" :style="{ width: timelineWidth + 'px' }">
          <div 
            v-for="tick in timeRulerTicks" 
            :key="tick.time"
            class="ruler-tick"
            :style="{ left: tick.position + 'px' }"
          >
            <div class="tick-mark" :class="tick.type"></div>
            <div class="tick-label" v-if="tick.type === 'major'">{{ formatTime(tick.time) }}</div>
          </div>
        </div>

        <!-- 播放头 -->
        <div 
          class="playhead"
          :style="{ left: playheadPosition + 'px' }"
        >
          <div class="playhead-line"></div>
          <div class="playhead-handle"></div>
        </div>

        <!-- 视频轨道 -->
        <div 
          class="timeline-track"
          :style="{ width: timelineWidth + 'px' }"
          @drop="handleTrackDrop($event)"
          @dragover.prevent
          @click="clickTimeline($event)"
        >
          <div class="track-label">
            <span>{{ $t('video.videoTrack') }}</span>
            <el-button 
              type="text" 
              size="small" 
              @click.stop="clearAllClips"
              :disabled="timelineClips.length === 0"
              :title="$t('video.clearTrack')"
            >
              <el-icon><Delete /></el-icon>
            </el-button>
          </div>
          <div class="track-clips">
            <!-- 视频片段 -->
            <div
              v-for="(clip, index) in timelineClips"
              :key="clip.id"
              class="track-clip"
              :class="{ selected: selectedClipId === clip.id }"
              :style="getClipStyle(clip)"
              @click.stop="selectClip(clip)"
              @mousedown="startDragClip($event, clip)"
            >
              <div class="clip-content">
                <div class="clip-thumbnail">
                  <video :src="clip.video_url" />
                </div>
                <div class="clip-info">
                  <div class="clip-title">{{ $t('storyboard.scene') }} {{ clip.storyboard_number }}</div>
                  <div class="clip-duration">{{ clip.duration.toFixed(1) }}s</div>
                </div>
              </div>
              <div class="clip-resize-left" @mousedown.stop="startResizeClip($event, clip, 'left')"></div>
              <div class="clip-resize-right" @mousedown.stop="startResizeClip($event, clip, 'right')"></div>
              <div class="clip-remove" @click.stop="removeClip(clip)">
                <el-icon><Close /></el-icon>
              </div>
            </div>
            
            <!-- 转场指示器 -->
            <div
              v-for="(clip, index) in timelineClips.slice(1)"
              :key="'transition-' + clip.id"
              class="transition-indicator"
              :style="getTransitionStyle(clip)"
              @click.stop="openTransitionDialog(timelineClips[index])"
            >
              <el-icon><connection /></el-icon>
              <span class="transition-label">{{ getTransitionLabel(timelineClips[index]) }}</span>
            </div>
          </div>
        </div>

        <!-- 音频轨道 -->
        <div 
          v-if="showAudioTrack"
          class="timeline-track audio-track"
          :style="{ width: timelineWidth + 'px' }"
          @click="clickTimeline($event)"
        >
          <div class="track-label">
            <span>{{ $t('video.audioTrack') }}</span>
            <el-button 
              type="text" 
              size="small" 
              @click.stop="extractAllAudio"
              :disabled="timelineClips.length === 0"
:title="$t('video.extractAudio')"
            >
              <el-icon><Headset /></el-icon>
            </el-button>
          </div>
          <div class="track-clips">
            <!-- 音频片段 -->
            <div
              v-for="audio in audioClips"
              :key="audio.id"
              class="track-clip audio-clip"
              :class="{ selected: selectedAudioClipId === audio.id }"
              :style="getClipStyle(audio)"
              @click.stop="selectAudioClip(audio)"
              @mousedown="startDragAudioClip($event, audio)"
            >
              <div class="clip-content">
                <div class="audio-waveform">
                  <el-icon><Microphone /></el-icon>
                </div>
                <div class="clip-info">
                  <div class="clip-title">{{ $t('video.audio') }} {{ audio.order + 1 }}</div>
                  <div class="clip-duration">{{ audio.duration.toFixed(1) }}s</div>
                </div>
              </div>
              <div class="clip-resize-left" @mousedown.stop="startResizeAudioClip($event, audio, 'left')"></div>
              <div class="clip-resize-right" @mousedown.stop="startResizeAudioClip($event, audio, 'right')"></div>
              <div class="clip-remove" @click.stop="removeAudioClip(audio)">
                <el-icon><Close /></el-icon>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 转场设置对话框 -->
    <el-dialog
      v-model="transitionDialogVisible"
      title="设置转场效果"
      width="500px"
    >
      <el-form label-width="100px">
        <el-form-item :label="$t('video.transitionType')">
          <el-select v-model="editingTransition.type" :placeholder="$t('video.selectTransition')">
            <el-option label="无转场" value="none" />
            <!-- 淡入淡出类 -->
            <el-option label="淡入淡出" value="fade" />
            <el-option label="黑场过渡" value="fadeblack" />
            <el-option label="白场过渡" value="fadewhite" />
            <el-option label="灰场过渡" value="fadegrays" />
            <!-- 滑动类 -->
            <el-option label="左滑" value="slideleft" />
            <el-option label="右滑" value="slideright" />
            <el-option label="上滑" value="slideup" />
            <el-option label="下滑" value="slidedown" />
            <!-- 擦除类 -->
            <el-option label="左擦除" value="wipeleft" />
            <el-option label="右擦除" value="wiperight" />
            <el-option label="上擦除" value="wipeup" />
            <el-option label="下擦除" value="wipedown" />
            <!-- 圆形类 -->
            <el-option label="圆形展开" value="circleopen" />
            <el-option label="圆形收缩" value="circleclose" />
            <!-- 其他特效 -->
            <el-option label="溶解" value="dissolve" />
            <el-option label="距离" value="distance" />
            <el-option label="水平打开" value="horzopen" />
            <el-option label="水平关闭" value="horzclose" />
            <el-option label="垂直打开" value="vertopen" />
            <el-option label="垂直关闭" value="vertclose" />
          </el-select>
        </el-form-item>
        <el-form-item :label="$t('video.transitionDuration')" v-if="editingTransition.type !== 'none'">
          <el-slider
            v-model="editingTransition.duration"
            :min="0.3"
            :max="3"
            :step="0.1"
            show-input
            :format-tooltip="(val: number) => val.toFixed(1) + 's'"
          />
        </el-form-item>
        <el-alert
          v-if="editingTransition.type !== 'none'"
          title="注意：添加转场效果需要重新编码视频，处理时间会更长"
          type="warning"
          :closable="false"
          show-icon
        />
      </el-form>
      <template #footer>
        <el-button @click="transitionDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="applyTransition">确定</el-button>
      </template>
    </el-dialog>

    <!-- 合并进度对话框 -->
    <el-dialog 
      v-model="mergeDialogVisible" 
      title="视频合并中" 
      width="500px"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :show-close="!merging"
    >
      <div class="merge-progress-container">
        <div class="progress-info">
          <div class="progress-phase">
            <el-tag :type="getPhaseType(mergeProgressDetail.phase)">
              {{ getPhaseText(mergeProgressDetail.phase) }}
            </el-tag>
          </div>
          <div class="progress-message">{{ mergeProgressDetail.message }}</div>
        </div>
        
        <el-progress 
          :percentage="mergeProgressDetail.progress" 
          :status="mergeProgressDetail.phase === 'completed' ? 'success' : undefined"
          :stroke-width="20"
        />
        
        <div class="progress-tips">
          <p v-if="mergeProgressDetail.phase === 'loading'">
            <el-icon><Loading /></el-icon>
            正在加载FFmpeg引擎（首次需要下载约30MB）...
          </p>
          <p v-else-if="mergeProgressDetail.phase === 'processing'">
            <el-icon><Download /></el-icon>
            正在处理视频文件，请稍候...
          </p>
          <p v-else-if="mergeProgressDetail.phase === 'encoding'">
            <el-icon><VideoCamera /></el-icon>
            正在编码合并视频，可能需要几分钟...
          </p>
          <p v-else-if="mergeProgressDetail.phase === 'completed'">
            <el-icon><Check /></el-icon>
            合并完成！视频已自动下载。
          </p>
        </div>
      </div>
      
      <template #footer v-if="!merging">
        <el-button @click="mergeDialogVisible = false">关闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { 
  VideoPlay, VideoPause, Plus, FolderAdd, ArrowLeft, ArrowRight,
  Scissor, Connection, Setting, ZoomIn, ZoomOut, Refresh, Download, Delete,
  Close, VideoCamera, Check, Loading, Headset, Microphone
} from '@element-plus/icons-vue'
import { videoMerger, type MergeProgress } from '@/utils/videoMerger'
import { trimAndMergeVideos } from '@/utils/ffmpeg'

interface Scene {
  id: string
  storyboard_number: number
  title?: string
  description?: string
  location?: string
  time?: string
  video_url: string
  duration?: number
}

interface TimelineClip {
  id: string
  storyboard_id: string
  storyboard_number: number
  video_url: string
  start_time: number
  end_time: number
  duration: number
  position: number  // 在时间线上的位置（秒）
  order: number
  transition?: {
    type: 'fade' | 'fadeblack' | 'fadewhite' | 'fadegrays' | 'slideleft' | 'slideright' | 'slideup' | 'slidedown' | 'wipeleft' | 'wiperight' | 'wipeup' | 'wipedown' | 'circleopen' | 'circleclose' | 'dissolve' | 'distance' | 'horzopen' | 'horzclose' | 'vertopen' | 'vertclose' | 'none'
    duration: number
  }
  audio_url?: string  // 提取的音频URL
  muted?: boolean     // 是否静音
}

interface AudioClip {
  id: string
  source_clip_id: string  // 关联的视频片段ID
  audio_url: string
  start_time: number
  end_time: number
  duration: number
  position: number
  order: number
  volume: number  // 音量 0-1
}

const props = defineProps<{
  scenes: Scene[]
  episodeId: string
  dramaId: string
  assets?: any[]
}>()

const emit = defineEmits<{
  (e: 'merge-completed', mergeId: number): void
  (e: 'asset-deleted'): void
}>()

// 基础状态
const availableStoryboards = computed(() => {
  const assets = (props.assets || [])
    .filter(a => {
      const isValid = a.type === 'video' && a.url
      return isValid
    })
    .map(a => ({
      id: `asset_${a.id}`,
      storyboard_number: a.storyboard_num || a.id,
      storyboard_num: a.storyboard_num,
      storyboard_id: a.storyboard_id,
      video_url: a.url,
      duration: a.duration || 0,
      name: a.name,
      isAsset: true,
      assetId: a.id
    }))
    .sort((a, b) => {
      // 优先按storyboard_num排序，如果没有则按storyboard_id排序，最后按asset id排序
      const aNum = a.storyboard_num || a.storyboard_id || a.assetId
      const bNum = b.storyboard_num || b.storyboard_id || b.assetId
      return aNum - bNum
    })
  return assets
})
const timelineClips = ref<TimelineClip[]>([])
const audioClips = ref<AudioClip[]>([])
const selectedClipId = ref<string | null>(null)
const selectedAudioClipId = ref<string | null>(null)
const previewPlayer = ref<HTMLVideoElement | null>(null)
const audioPlayer = ref<HTMLAudioElement | null>(null)
const timelineContainer = ref<HTMLElement | null>(null)
const showAudioTrack = ref(true)  // 是否显示音频轨道

// 时间线状态
const currentTime = ref(0)
const zoom = ref(1) // 缩放级别
const pixelsPerSecond = computed(() => 50 * zoom.value) // 每秒对应的像素数
const isPlaying = ref(false)
const playbackTimer = ref<number | null>(null)

// 转场预览状态（必须在模板使用前定义）
const transitionState = ref({
  active: false,
  type: 'fade',
  phase: 'in' as 'in' | 'out',
  duration: 1.0
})

// 导出状态
const merging = ref(false)
const serverMerging = ref(false)
const mergeProgress = ref(0)
const mergeDialogVisible = ref(false)
const mergeProgressDetail = ref<MergeProgress>({
  phase: 'loading',
  progress: 0,
  message: ''
})

// 转场设置状态
const transitionDialogVisible = ref(false)
const editingTransitionClipId = ref<string | null>(null)
const editingTransition = ref({
  type: 'fade' as 'fade' | 'fadeblack' | 'fadewhite' | 'fadegrays' | 'slideleft' | 'slideright' | 'slideup' | 'slidedown' | 'wipeleft' | 'wiperight' | 'wipeup' | 'wipedown' | 'circleopen' | 'circleclose' | 'dissolve' | 'distance' | 'horzopen' | 'horzclose' | 'vertopen' | 'vertclose' | 'none',
  duration: 1.0
})

// 计算总时长
const totalDuration = computed(() => {
  if (timelineClips.value.length === 0) return 0
  const lastClip = timelineClips.value[timelineClips.value.length - 1]
  return lastClip ? lastClip.position + lastClip.duration : 0
})

// 工具函数
const formatTime = (seconds: number) => {
  const mins = Math.floor(seconds / 60)
  const secs = Math.floor(seconds % 60)
  const ms = Math.floor((seconds % 1) * 10)
  return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}.${ms}`
}

const getSceneDesc = (scene: Scene) => {
  const parts = []
  if (scene.location) parts.push(scene.location)
  if (scene.time) parts.push(scene.time)
  return parts.join(' · ') || (scene.description?.slice(0, 15) + '...' || '无描述')
}

// 预览相关
const currentPreviewUrl = computed(() => {
  if (timelineClips.value.length === 0) return ''
  // 根据当前时间找到应该播放的片段
  const clip = timelineClips.value.find(c => 
    currentTime.value >= c.position && currentTime.value < c.position + c.duration
  )
  return clip?.video_url || timelineClips.value[0]?.video_url || ''
})

// 当前音频URL
const currentAudioUrl = computed(() => {
  if (audioClips.value.length === 0) return ''
  // 根据当前时间找到应该播放的音频片段
  const audioClip = audioClips.value.find(a => 
    currentTime.value >= a.position && currentTime.value < a.position + a.duration
  )
  return audioClip?.audio_url || ''
})

const previewScene = (scene: Scene) => {
  if (previewPlayer.value) {
    previewPlayer.value.src = scene.video_url
    previewPlayer.value.play()
  }
}

const handlePreviewLoaded = () => {
  // 视频加载完成后跳转到正确的时间点
  if (previewPlayer.value) {
    const clip = timelineClips.value.find(c => 
      currentTime.value >= c.position && currentTime.value < c.position + c.duration
    )
    if (clip) {
      const offsetInClip = currentTime.value - clip.position
      previewPlayer.value.currentTime = clip.start_time + offsetInClip
    }
  }
}

const handleAudioLoaded = () => {
  // 音频加载完成后跳转到正确的时间点
  if (audioPlayer.value && audioClips.value.length > 0) {
    const audioClip = audioClips.value.find(a => 
      currentTime.value >= a.position && currentTime.value < a.position + a.duration
    )
    if (audioClip) {
      const offsetInClip = currentTime.value - audioClip.position
      audioPlayer.value.currentTime = audioClip.start_time + offsetInClip
    }
  }
}

const handleAudioEnded = () => {
  // 音频自然结束，尝试播放下一个音频片段
  const currentAudio = audioClips.value.find(a => 
    currentTime.value >= a.position && currentTime.value < a.position + a.duration
  )
  
  if (currentAudio) {
    const currentIndex = audioClips.value.findIndex(a => a.id === currentAudio.id)
    const nextAudio = audioClips.value[currentIndex + 1]
    
    if (nextAudio && isPlaying.value) {
      // 有下一个音频片段且正在播放，继续
      // 时间线会自动更新到下一个片段
    }
  }
}

const handlePreviewTimeUpdate = () => {
  if (!isPlaying.value || !previewPlayer.value) return
  
  // 找到当前播放的片段
  const currentClip = timelineClips.value.find(c => 
    currentTime.value >= c.position && currentTime.value < c.position + c.duration
  )
  
  if (!currentClip) {
    pauseTimeline()
    return
  }
  
  // 计算时间线上的当前位置
  const videoTime = previewPlayer.value.currentTime
  const clipOffset = videoTime - currentClip.start_time
  currentTime.value = currentClip.position + clipOffset
  
  // 检查是否播放到片段结尾（提前0.1秒检测，避免播放完才切换）
  if (videoTime >= currentClip.end_time - 0.1) {
    // 查找下一个片段
    const currentIndex = timelineClips.value.findIndex(c => c.id === currentClip.id)
    const nextClip = timelineClips.value[currentIndex + 1]
    
    if (nextClip) {
      // 切换到下一个片段
      switchToClip(nextClip)
    } else {
      // 没有下一个片段，停止播放
      pauseTimeline()
      currentTime.value = totalDuration.value
    }
  }
}

const switchToClip = async (clip: TimelineClip) => {
  if (!previewPlayer.value) return
  
  // 获取转场配置
  const transition = clip.transition
  const hasTransition = transition && transition.type !== 'none'
  const transitionDuration = hasTransition ? (transition.duration * 1000) : 0
  
  if (hasTransition) {
    // 触发转场效果
    transitionState.value = {
      active: true,
      type: transition.type,
      phase: 'out',
      duration: transition.duration
    }
    
    // 等待转场动画完成一半
    await new Promise(resolve => setTimeout(resolve, transitionDuration / 2))
  }
  
  // 暂停当前播放，避免冲突
  previewPlayer.value.pause()
  if (audioPlayer.value) {
    audioPlayer.value.pause()
  }
  
  // 切换视频源
  currentTime.value = clip.position
  previewPlayer.value.src = clip.video_url
  
  // 同步切换音频源
  if (audioClips.value.length > 0 && audioPlayer.value) {
    const audioClip = audioClips.value.find(a => 
      clip.position >= a.position && clip.position < a.position + a.duration
    )
    if (audioClip) {
      audioPlayer.value.src = audioClip.audio_url
    }
  }
  
  // 等待视频加载
  try {
    await new Promise((resolve, reject) => {
      if (!previewPlayer.value) return reject()
      
      const onCanPlay = () => {
        previewPlayer.value?.removeEventListener('canplay', onCanPlay)
        previewPlayer.value?.removeEventListener('error', onError)
        resolve(undefined)
      }
      
      const onError = () => {
        previewPlayer.value?.removeEventListener('canplay', onCanPlay)
        previewPlayer.value?.removeEventListener('error', onError)
        reject()
      }
      
      previewPlayer.value.addEventListener('canplay', onCanPlay)
      previewPlayer.value.addEventListener('error', onError)
    })
    
    // 设置起始时间并播放
    previewPlayer.value.currentTime = clip.start_time
    
    if (hasTransition) {
      // 切换到转场入场阶段
      transitionState.value.phase = 'in'
      
      // 等待转场剩余时间
      setTimeout(() => {
        transitionState.value.active = false
      }, transitionDuration / 2)
    }
    
    if (isPlaying.value) {
      await previewPlayer.value.play()
      
      // 同步播放音频
      if (audioClips.value.length > 0 && audioPlayer.value) {
        const audioClip = audioClips.value.find(a => 
          clip.position >= a.position && clip.position < a.position + a.duration
        )
        if (audioClip && audioPlayer.value.src) {
          audioPlayer.value.currentTime = audioClip.start_time
          audioPlayer.value.play().catch(err => {
            console.warn('音频播放失败:', err)
          })
        }
      }
    }
  } catch (error) {
    console.error('切换视频片段失败:', error)
    transitionState.value.active = false
    pauseTimeline()
  }
}

const handlePreviewEnded = () => {
  // 视频自然结束，尝试播放下一个片段
  const currentClip = timelineClips.value.find(c => 
    currentTime.value >= c.position && currentTime.value < c.position + c.duration
  )
  
  if (currentClip) {
    const currentIndex = timelineClips.value.findIndex(c => c.id === currentClip.id)
    const nextClip = timelineClips.value[currentIndex + 1]
    
    if (nextClip) {
      currentTime.value = nextClip.position
      seekToTime(nextClip.position)
    } else {
      pauseTimeline()
    }
  }
}

// 时间线计算
const timelineWidth = computed(() => {
  const duration = Math.max(totalDuration.value, 30)
  const contentWidth = duration * pixelsPerSecond.value
  const minContentWidth = 800 // 最小内容宽度
  return 100 + Math.max(contentWidth, minContentWidth) + 100 // 100px左边距 + 100px右边距
})

const playheadPosition = computed(() => {
  return 100 + currentTime.value * pixelsPerSecond.value
})

const timeRulerTicks = computed(() => {
  const ticks = []
  const duration = Math.max(totalDuration.value, 30)
  const interval = zoom.value >= 1.5 ? 1 : zoom.value >= 0.5 ? 5 : 10
  
  for (let i = 0; i <= duration; i += interval) {
    ticks.push({
      time: i,
      position: 100 + i * pixelsPerSecond.value,
      type: i % (interval * 2) === 0 ? 'major' : 'minor'
    })
  }
  return ticks
})

// 片段样式计算
const getClipStyle = (clip: TimelineClip) => {
  return {
    left: 100 + clip.position * pixelsPerSecond.value + 'px',
    width: clip.duration * pixelsPerSecond.value + 'px'
  }
}

// 拖拽场景到时间线
const handleDragStart = (event: DragEvent, scene: Scene) => {
  if (event.dataTransfer) {
    event.dataTransfer.effectAllowed = 'copy'
    event.dataTransfer.setData('scene', JSON.stringify(scene))
  }
}

const handleTrackDrop = (event: DragEvent) => {
  event.preventDefault()
  const sceneData = event.dataTransfer?.getData('scene')
  if (!sceneData) return
  
  const scene = JSON.parse(sceneData) as Scene
  
  // 默认添加到末尾，不使用拖拽位置（避免产生空隙）
  addClipToTimeline(scene)
}

const getVideoDuration = (videoUrl: string): Promise<number> => {
  return new Promise((resolve, reject) => {
    const video = document.createElement('video')
    video.preload = 'metadata'
    video.src = videoUrl
    
    video.onloadedmetadata = () => {
      const duration = video.duration
      video.remove()
      resolve(duration)
    }
    
    video.onerror = () => {
      video.remove()
      reject(new Error('Failed to load video'))
    }
  })
}

const addClipToTimeline = async (scene: Scene, insertAtPosition?: number) => {
  // 获取视频真实时长
  let videoDuration = scene.duration || 5
  if (scene.video_url) {
    try {
      videoDuration = await getVideoDuration(scene.video_url)
    } catch (error) {
      console.warn('Failed to get video duration, using default or scene duration:', error)
      videoDuration = scene.duration || 5
    }
  }

  // 计算新片段的位置
  let clipPosition: number
  let insertAfterIndex: number | null = null
  
  if (insertAtPosition !== undefined && timelineClips.value.length > 0) {
    // 如果指定了插入位置,找到应该插入的位置
    clipPosition = insertAtPosition
  } else if (selectedClipId.value && timelineClips.value.length > 0) {
    // 如果有选中的片段，插入到选中片段之后
    const selectedIndex = timelineClips.value.findIndex(c => c.id === selectedClipId.value)
    if (selectedIndex !== -1) {
      const selectedClip = timelineClips.value[selectedIndex]
      clipPosition = selectedClip.position + selectedClip.duration
      insertAfterIndex = selectedIndex
    } else {
      // 选中的片段不存在，添加到末尾
      const lastClip = timelineClips.value[timelineClips.value.length - 1]
      clipPosition = lastClip.position + lastClip.duration
    }
  } else {
    // 默认添加到末尾（紧密连接）
    if (timelineClips.value.length === 0) {
      clipPosition = 0 // 第一个片段从0开始
    } else {
      // 添加到最后一个片段的结尾
      const lastClip = timelineClips.value[timelineClips.value.length - 1]
      clipPosition = lastClip.position + lastClip.duration
    }
  }
  
  const newClip: TimelineClip = {
    id: `clip_${Date.now()}_${scene.id}`,
    storyboard_id: scene.storyboard_id,
    storyboard_number: scene.storyboard_number,
    video_url: scene.video_url,
    start_time: 0,
    end_time: videoDuration,
    duration: videoDuration,
    position: clipPosition,
    order: timelineClips.value.length,
    transition: {
      type: 'fade',
      duration: 1.0
    }
  }
  
  // 如果是插入到中间，需要调整后续片段的位置
  if (insertAfterIndex !== null && insertAfterIndex < timelineClips.value.length - 1) {
    const newDuration = newClip.duration
    // 将后续所有片段向后移动
    for (let i = insertAfterIndex + 1; i < timelineClips.value.length; i++) {
      timelineClips.value[i].position += newDuration
    }
  }
  
  timelineClips.value.push(newClip)
  timelineClips.value.sort((a, b) => a.position - b.position)
  updateClipOrders()
  
  // 选中新添加的片段
  selectedClipId.value = newClip.id
  
  const insertInfo = insertAfterIndex !== null ? '（已插入到选中片段后）' : ''
  ElMessage.success(`已添加到时间线${insertInfo}`)
}

// 一键添加全部场景
const addAllScenesInOrder = async () => {
  if (availableStoryboards.value.length === 0) {
    ElMessage.warning('没有可用的场景')
    return
  }

  // 按场景编号排序
  const sortedScenes = [...availableStoryboards.value].sort((a, b) => 
    a.storyboard_number - b.storyboard_number
  )

  // 清空当前选中，让所有场景都添加到末尾
  selectedClipId.value = null

  // 批量添加（顺序添加以确保正确的时长）
  for (const scene of sortedScenes) {
    await addClipToTimeline(scene)
  }

  ElMessage.success(`已批量添加 ${sortedScenes.length} 个场景到时间线`)
}

// 删除素材
const deleteAsset = async (scene: any) => {
  if (!scene.isAsset) {
    ElMessage.warning('只能删除素材库中的视频')
    return
  }

  try {
    // 直接调用API删除
    const { assetAPI } = await import('@/api/asset')
    await assetAPI.deleteAsset(scene.assetId)
    
    ElMessage.success('删除成功')
    
    // 通知父组件刷新素材列表
    emit('asset-deleted')
  } catch (error: any) {
    console.error('删除素材失败:', error)
    ElMessage.error(error.message || '删除失败')
  }
}

// 转场相关方法
const getTransitionStyle = (clip: TimelineClip) => {
  // 转场指示器显示在片段开始位置
  return {
    left: 100 + clip.position * pixelsPerSecond.value - 15 + 'px'
  }
}

const getTransitionLabel = (clip: TimelineClip) => {
  if (!clip.transition || clip.transition.type === 'none') {
    return '无'
  }
  const labels: Record<string, string> = {
    'fade': '淡入',
    'fadeblack': '黑场',
    'fadewhite': '白场',
    'fadegrays': '灰场',
    'slideleft': '左滑',
    'slideright': '右滑',
    'slideup': '上滑',
    'slidedown': '下滑',
    'wipeleft': '左擦',
    'wiperight': '右擦',
    'wipeup': '上擦',
    'wipedown': '下擦',
    'circleopen': '圆开',
    'circleclose': '圆关',
    'dissolve': '溶解',
    'distance': '距离',
    'horzopen': '水平开',
    'horzclose': '水平关',
    'vertopen': '垂直开',
    'vertclose': '垂直关'
  }
  return labels[clip.transition.type] || '转场'
}

const openTransitionDialog = (clip: TimelineClip) => {
  console.log('🎬 打开转场设置对话框:', {
    clip_id: clip.id,
    storyboard_id: clip.storyboard_id,
    order: clip.order,
    current_transition: clip.transition
  })
  editingTransitionClipId.value = clip.id
  editingTransition.value = {
    type: clip.transition?.type || 'fade',
    duration: clip.transition?.duration || 1.0
  }
  transitionDialogVisible.value = true
}

const applyTransition = () => {
  const clip = timelineClips.value.find(c => c.id === editingTransitionClipId.value)
  if (clip) {
    clip.transition = {
      type: editingTransition.value.type,
      duration: editingTransition.value.duration
    }
    console.log('✅ 转场效果已设置:', {
      clip_id: clip.id,
      storyboard_id: clip.storyboard_id,
      order: clip.order,
      transition: clip.transition
    })
    ElMessage.success('转场效果已设置')
  } else {
    console.error('❌ 未找到目标片段:', editingTransitionClipId.value)
  }
  transitionDialogVisible.value = false
}

// 选择和删除片段
const selectClip = (clip: TimelineClip) => {
  selectedClipId.value = clip.id
}

const removeClip = (clip: TimelineClip) => {
  const index = timelineClips.value.findIndex(c => c.id === clip.id)
  if (index !== -1) {
    timelineClips.value.splice(index, 1)
    updateClipOrders()
    
    // 同时移除关联的音频片段
    const audioIndex = audioClips.value.findIndex(a => a.source_clip_id === clip.id)
    if (audioIndex !== -1) {
      audioClips.value.splice(audioIndex, 1)
      updateAudioClipOrders()
    }
  }
}

const clearAllClips = () => {
  if (timelineClips.value.length === 0) return
  
  timelineClips.value = []
  audioClips.value = []
  selectedClipId.value = null
  selectedAudioClipId.value = null
  currentTime.value = 0
  ElMessage.success('已清空轨道')
}

const updateClipOrders = () => {
  timelineClips.value.forEach((clip, index) => {
    clip.order = index
  })
}

// 音频片段管理
const extractAllAudio = async () => {
  if (timelineClips.value.length === 0) {
    ElMessage.warning('时间线上没有视频片段')
    return
  }

  const loadingMessage = ElMessage.info({
    message: '正在从视频中提取音频轨道，请稍候...',
    duration: 0
  })
  
  try {
    // 清空现有音频
    audioClips.value = []
    
    // 收集所有视频URL
    const videoUrls = timelineClips.value.map(clip => clip.video_url)
    
    // 调用后端API批量提取音频
    const { audioAPI } = await import('@/api/audio')
    const response = await audioAPI.batchExtractAudio(videoUrls)
    
    if (!response.results || response.results.length === 0) {
      throw new Error('音频提取失败，未返回结果')
    }
    
    // 为每个视频片段创建对应的音频片段
    timelineClips.value.forEach((clip, index) => {
      const extractedAudio = response.results[index]
      if (!extractedAudio) {
        console.warn(`视频片段 ${index} 未能提取音频`)
        return
      }
      
      // 验证音频时长
      const audioDuration = extractedAudio.duration
      if (!audioDuration || audioDuration <= 0) {
        console.error(`音频片段 ${index} 时长无效:`, audioDuration)
        throw new Error(`音频片段 ${index + 1} 时长无效`)
      }
      
      console.log(`音频片段 ${index}:`, {
        video_duration: clip.duration,
        audio_duration: audioDuration,
        video_position: clip.position,
        video_url: clip.video_url,
        audio_url: extractedAudio.audio_url
      })
      
      const audioClip: AudioClip = {
        id: `audio_${Date.now()}_${index}`,
        source_clip_id: clip.id,
        audio_url: extractedAudio.audio_url,
        start_time: 0, // 音频从头开始播放
        end_time: audioDuration, // 使用实际音频时长
        duration: audioDuration, // 使用提取的音频时长
        position: clip.position, // 和视频片段在时间轴上相同位置
        order: index,
        volume: 1.0
      }
      audioClips.value.push(audioClip)
    })
    
    updateAudioClipOrders()
    loadingMessage.close()
    ElMessage.success(`已成功提取 ${audioClips.value.length} 个音频片段`)
  } catch (error: any) {
    console.error('提取音频失败:', error)
    loadingMessage.close()
    ElMessage.error(error.message || '音频提取失败，请重试')
    // 清空部分提取的音频
    audioClips.value = []
  }
}

const selectAudioClip = (audio: AudioClip) => {
  selectedAudioClipId.value = audio.id
  // 取消选中视频片段
  selectedClipId.value = null
}

const removeAudioClip = (audio: AudioClip) => {
  const index = audioClips.value.findIndex(a => a.id === audio.id)
  if (index !== -1) {
    audioClips.value.splice(index, 1)
    updateAudioClipOrders()
  }
}

const updateAudioClipOrders = () => {
  audioClips.value.forEach((clip, index) => {
    clip.order = index
  })
}

// 拖拽音频片段
const startDragAudioClip = (event: MouseEvent, audio: AudioClip) => {
  if (dragState.value.isResizing) return
  
  event.stopPropagation()
  dragState.value = {
    isDragging: true,
    isResizing: false,
    clipId: audio.id,
    startX: event.clientX,
    startPosition: audio.position,
    startTime: 0,
    originalDuration: audio.duration
  }
  
  selectedAudioClipId.value = audio.id
  document.addEventListener('mousemove', handleDragAudioMove)
  document.addEventListener('mouseup', handleDragAudioEnd)
}

const handleDragAudioMove = (event: MouseEvent) => {
  if (!dragState.value.isDragging || !dragState.value.clipId) return
  
  const audio = audioClips.value.find(a => a.id === dragState.value.clipId)
  if (!audio) return
  
  const deltaX = event.clientX - dragState.value.startX
  const deltaTime = deltaX / pixelsPerSecond.value
  const newPosition = Math.max(0, dragState.value.startPosition + deltaTime)
  
  audio.position = newPosition
}

const handleDragAudioEnd = () => {
  dragState.value.isDragging = false
  dragState.value.clipId = null
  
  document.removeEventListener('mousemove', handleDragAudioMove)
  document.removeEventListener('mouseup', handleDragAudioEnd)
  
  // 重新排序
  audioClips.value.sort((a, b) => a.position - b.position)
  updateAudioClipOrders()
}

// 调整音频片段大小
const startResizeAudioClip = (event: MouseEvent, audio: AudioClip, side: 'left' | 'right') => {
  event.stopPropagation()
  
  dragState.value = {
    isDragging: false,
    isResizing: true,
    resizeSide: side,
    clipId: audio.id,
    startX: event.clientX,
    startPosition: audio.position,
    startTime: audio.start_time,
    originalDuration: audio.duration
  }
  
  selectedAudioClipId.value = audio.id
  document.addEventListener('mousemove', handleResizeAudioMove)
  document.addEventListener('mouseup', handleResizeAudioEnd)
}

const handleResizeAudioMove = (event: MouseEvent) => {
  if (!dragState.value.isResizing || !dragState.value.clipId) return
  
  const audio = audioClips.value.find(a => a.id === dragState.value.clipId)
  if (!audio) return
  
  const deltaX = event.clientX - dragState.value.startX
  const deltaTime = deltaX / pixelsPerSecond.value
  
  if (dragState.value.resizeSide === 'left') {
    const newStartTime = Math.max(0, dragState.value.startTime + deltaTime)
    const maxStartTime = dragState.value.startTime + dragState.value.originalDuration - 0.1
    
    audio.start_time = Math.min(newStartTime, maxStartTime)
    audio.position = dragState.value.startPosition + deltaTime
    audio.duration = dragState.value.originalDuration - (audio.start_time - dragState.value.startTime)
  } else {
    const newDuration = Math.max(0.1, dragState.value.originalDuration + deltaTime)
    const maxDuration = (audio.end_time - audio.start_time)
    
    audio.duration = Math.min(newDuration, maxDuration)
    audio.end_time = audio.start_time + audio.duration
  }
}

const handleResizeAudioEnd = () => {
  dragState.value.isResizing = false
  dragState.value.clipId = null
  
  document.removeEventListener('mousemove', handleResizeAudioMove)
  document.removeEventListener('mouseup', handleResizeAudioEnd)
}

// 拖拽和调整片段
interface DragState {
  isDragging: boolean
  isResizing: boolean
  resizeSide?: 'left' | 'right'
  clipId: string | null
  startX: number
  startPosition: number
  startTime: number
  originalDuration: number
}

const dragState = ref<DragState>({
  isDragging: false,
  isResizing: false,
  clipId: null,
  startX: 0,
  startPosition: 0,
  startTime: 0,
  originalDuration: 0
})

// 拖拽移动片段位置
const startDragClip = (event: MouseEvent, clip: TimelineClip) => {
  if (dragState.value.isResizing) return
  
  event.stopPropagation()
  dragState.value = {
    isDragging: true,
    isResizing: false,
    clipId: clip.id,
    startX: event.clientX,
    startPosition: clip.position,
    startTime: 0,
    originalDuration: clip.duration
  }
  
  selectedClipId.value = clip.id
  document.addEventListener('mousemove', handleDragMove)
  document.addEventListener('mouseup', handleDragEnd)
}

const handleDragMove = (event: MouseEvent) => {
  if (!dragState.value.clipId) return
  
  const clip = timelineClips.value.find(c => c.id === dragState.value.clipId)
  if (!clip) return
  
  if (dragState.value.isDragging) {
    // 计算新位置
    const deltaX = event.clientX - dragState.value.startX
    const deltaTime = deltaX / pixelsPerSecond.value
    let newPosition = Math.max(0, dragState.value.startPosition + deltaTime)
    
    // 吸附到其他片段边缘
    newPosition = snapToNearby(newPosition, clip.id, clip.duration)
    
    clip.position = newPosition
    updateClipOrders()
  } else if (dragState.value.isResizing) {
    handleResizeMove(event, clip)
  }
}

const handleDragEnd = () => {
  dragState.value = {
    isDragging: false,
    isResizing: false,
    clipId: null,
    startX: 0,
    startPosition: 0,
    startTime: 0,
    originalDuration: 0
  }
  
  document.removeEventListener('mousemove', handleDragMove)
  document.removeEventListener('mouseup', handleDragEnd)
  
  // 重新排序片段并紧密连接
  timelineClips.value.sort((a, b) => a.position - b.position)
  compactClips()
  updateClipOrders()
}

// 紧密排列所有片段（消除空隙）
const compactClips = () => {
  let currentPosition = 0
  for (const clip of timelineClips.value) {
    clip.position = currentPosition
    currentPosition += clip.duration
  }
}

// 调整片段时长
const startResizeClip = (event: MouseEvent, clip: TimelineClip, side: 'left' | 'right') => {
  event.stopPropagation()
  
  dragState.value = {
    isDragging: false,
    isResizing: true,
    resizeSide: side,
    clipId: clip.id,
    startX: event.clientX,
    startPosition: clip.position,
    startTime: side === 'left' ? clip.start_time : clip.end_time,
    originalDuration: clip.duration
  }
  
  selectedClipId.value = clip.id
  document.addEventListener('mousemove', handleDragMove)
  document.addEventListener('mouseup', handleDragEnd)
}

const handleResizeMove = (event: MouseEvent, clip: TimelineClip) => {
  const deltaX = event.clientX - dragState.value.startX
  const deltaTime = deltaX / pixelsPerSecond.value
  
  if (dragState.value.resizeSide === 'left') {
    // 调整开始时间（不改变位置，只改变裁剪点）
    const newStartTime = Math.max(0, dragState.value.startTime + deltaTime)
    const maxStartTime = clip.end_time - 0.1 // 至少保留0.1秒
    
    clip.start_time = Math.min(newStartTime, maxStartTime)
    clip.duration = clip.end_time - clip.start_time
    
    // 调整左边缘后需要重新紧密连接
    const clipIndex = timelineClips.value.findIndex(c => c.id === clip.id)
    if (clipIndex > 0) {
      // 调整前面片段的结束位置
      compactClipsFromIndex(clipIndex)
    }
  } else {
    // 调整结束时间
    const scene = props.scenes.find(s => s.id === clip.scene_id)
    const maxDuration = scene?.duration || 10
    const maxEndTime = clip.start_time + maxDuration
    
    const newEndTime = Math.max(clip.start_time + 0.1, dragState.value.startTime + deltaTime)
    clip.end_time = Math.min(newEndTime, maxEndTime)
    clip.duration = clip.end_time - clip.start_time
    
    // 调整右边缘后需要重新紧密连接后续片段
    const clipIndex = timelineClips.value.findIndex(c => c.id === clip.id)
    if (clipIndex < timelineClips.value.length - 1) {
      compactClipsFromIndex(clipIndex + 1)
    }
  }
}

// 从指定索引开始重新紧密排列片段
const compactClipsFromIndex = (startIndex: number) => {
  if (startIndex >= timelineClips.value.length) return
  
  for (let i = startIndex; i < timelineClips.value.length; i++) {
    if (i === 0) {
      timelineClips.value[i].position = 0
    } else {
      const prevClip = timelineClips.value[i - 1]
      timelineClips.value[i].position = prevClip.position + prevClip.duration
    }
  }
}

// 吸附到附近片段
const snapToNearby = (position: number, clipId: string, duration: number): number => {
  const snapThreshold = 5 / pixelsPerSecond.value // 5像素的吸附范围
  
  for (const other of timelineClips.value) {
    if (other.id === clipId) continue
    
    const otherEnd = other.position + other.duration
    
    // 吸附到前一个片段的结尾
    if (Math.abs(position - otherEnd) < snapThreshold) {
      return otherEnd
    }
    
    // 吸附到后一个片段的开头
    if (Math.abs(position + duration - other.position) < snapThreshold) {
      return other.position - duration
    }
  }
  
  // 吸附到起点
  if (position < snapThreshold) {
    return 0
  }
  
  return position
}

// 缩放控制
const zoomIn = () => {
  zoom.value = Math.min(zoom.value * 1.2, 3)
}

const zoomOut = () => {
  zoom.value = Math.max(zoom.value / 1.2, 0.3)
}

const zoomReset = () => {
  zoom.value = 1
}

// 时间线点击跳转
const clickTimeline = (event: MouseEvent) => {
  if (dragState.value.isDragging || dragState.value.isResizing) return
  
  const rect = (event.currentTarget as HTMLElement).getBoundingClientRect()
  const clickX = event.clientX - rect.left - 100
  const newTime = Math.max(0, clickX / pixelsPerSecond.value)
  seekToTime(newTime)
}

const seekToTime = (time: number) => {
  currentTime.value = time
  
  // 找到对应时间的视频片段并播放
  const clip = timelineClips.value.find(c => 
    time >= c.position && time < c.position + c.duration
  )
  
  if (clip && previewPlayer.value) {
    // 切换视频源（如果需要）
    if (previewPlayer.value.src !== clip.video_url) {
      previewPlayer.value.src = clip.video_url
    }
    
    // 跳转到片段内的对应时间
    const offsetInClip = time - clip.position
    previewPlayer.value.currentTime = clip.start_time + offsetInClip
    
    if (isPlaying.value) {
      previewPlayer.value.play()
    }
  }
  
  // 同步音频播放器
  if (audioClips.value.length > 0 && audioPlayer.value) {
    const audioClip = audioClips.value.find(a => 
      time >= a.position && time < a.position + a.duration
    )
    
    if (audioClip) {
      // 切换音频源（如果需要）
      if (audioPlayer.value.src !== audioClip.audio_url) {
        audioPlayer.value.src = audioClip.audio_url
      }
      
      // 跳转到音频片段内的对应时间
      const offsetInAudioClip = time - audioClip.position
      audioPlayer.value.currentTime = audioClip.start_time + offsetInAudioClip
      
      if (isPlaying.value) {
        audioPlayer.value.play().catch(err => {
          console.warn('音频播放失败:', err)
        })
      }
    } else {
      // 当前位置没有音频，暂停音频播放器
      audioPlayer.value.pause()
    }
  }
}

// 播放控制
const playTimeline = () => {
  if (timelineClips.value.length === 0) {
    ElMessage.warning('时间线中没有视频片段')
    return
  }
  
  isPlaying.value = true
  
  // 找到当前时间对应的视频片段
  const clip = timelineClips.value.find(c => 
    currentTime.value >= c.position && currentTime.value < c.position + c.duration
  )
  
  if (clip && previewPlayer.value) {
    if (previewPlayer.value.src !== clip.video_url) {
      previewPlayer.value.src = clip.video_url
    }
    const offsetInClip = currentTime.value - clip.position
    previewPlayer.value.currentTime = clip.start_time + offsetInClip
    previewPlayer.value.play()
  } else if (timelineClips.value[0]) {
    // 如果当前时间超出范围，从头开始播放
    currentTime.value = 0
    seekToTime(0)
    previewPlayer.value?.play()
  }
  
  // 同时播放音频（如果有）
  if (audioClips.value.length > 0 && audioPlayer.value) {
    const audioClip = audioClips.value.find(a => 
      currentTime.value >= a.position && currentTime.value < a.position + a.duration
    )
    
    if (audioClip) {
      if (audioPlayer.value.src !== audioClip.audio_url) {
        audioPlayer.value.src = audioClip.audio_url
      }
      const offsetInAudioClip = currentTime.value - audioClip.position
      audioPlayer.value.currentTime = audioClip.start_time + offsetInAudioClip
      audioPlayer.value.play().catch(err => {
        console.warn('音频播放失败:', err)
      })
    }
  }
}

const pauseTimeline = () => {
  isPlaying.value = false
  if (previewPlayer.value) {
    previewPlayer.value.pause()
  }
  // 同时暂停音频
  if (audioPlayer.value) {
    audioPlayer.value.pause()
  }
}

const togglePlay = () => {
  if (isPlaying.value) {
    pauseTimeline()
  } else {
    playTimeline()
  }
}

// 键盘快捷键
const handleKeyPress = (event: KeyboardEvent) => {
  // 如果在输入框中，不处理快捷键
  if ((event.target as HTMLElement).tagName === 'INPUT') return
  
  switch (event.code) {
    case 'Space':
      event.preventDefault()
      if (isPlaying.value) {
        pauseTimeline()
      } else {
        playTimeline()
      }
      break
    case 'Delete':
    case 'Backspace':
      if (selectedClipId.value) {
        event.preventDefault()
        const clip = timelineClips.value.find(c => c.id === selectedClipId.value)
        if (clip) removeClip(clip)
      }
      break
    case 'ArrowLeft':
      event.preventDefault()
      seekToTime(Math.max(0, currentTime.value - 1))
      break
    case 'ArrowRight':
      event.preventDefault()
      seekToTime(Math.min(totalDuration.value, currentTime.value + 1))
      break
    case 'Home':
      event.preventDefault()
      seekToTime(0)
      break
    case 'End':
      event.preventDefault()
      seekToTime(totalDuration.value)
      break
  }
}

// 生命周期管理
onMounted(() => {
  document.addEventListener('keydown', handleKeyPress)
})

onUnmounted(() => {
  document.removeEventListener('keydown', handleKeyPress)
  document.removeEventListener('mousemove', handleDragMove)
  document.removeEventListener('mouseup', handleDragEnd)
})

// 进度显示辅助函数
const getPhaseType = (phase: string) => {
  switch (phase) {
    case 'loading': return 'info'
    case 'processing': return 'warning'
    case 'encoding': return 'warning'
    case 'completed': return 'success'
    default: return 'info'
  }
}

const getPhaseText = (phase: string) => {
  switch (phase) {
    case 'loading': return '初始化'
    case 'processing': return '处理中'
    case 'encoding': return '编码中'
    case 'completed': return '完成'
    default: return '准备中'
  }
}

// 导出功能
const handleExport = async () => {
  if (timelineClips.value.length === 0) {
    ElMessage.warning('请至少添加一个视频片段')
    return
  }

  try {
    // 计算总视频大小（粗略估算）
    const totalSize = timelineClips.value.length * 20 // 假设每个片段约20MB
    const estimatedTime = Math.ceil(totalSize / 50) // 每50MB约1分钟
    
    await ElMessageBox.confirm(
      `即将在浏览器中合并 ${timelineClips.value.length} 个视频片段。\n\n` +
      `预计处理时间：${estimatedTime}-${estimatedTime + 1} 分钟\n` +
      `预计内存占用：约 ${Math.round(totalSize * 1.5)}MB\n\n` +
      `处理期间请勿关闭页面。`,
      '确认导出',
      {
        confirmButtonText: '开始合并',
        cancelButtonText: '取消',
        type: 'warning',
        dangerouslyUseHTMLString: true
      }
    )

    mergeDialogVisible.value = true
    merging.value = true

    // 初始化FFmpeg
    await videoMerger.initialize((progress) => {
      mergeProgress.value = progress
    })

    // 准备视频片段数据（包含转场信息）
    const clips = timelineClips.value.map(clip => ({
      url: clip.video_url,
      startTime: clip.start_time,
      endTime: clip.end_time,
      duration: clip.end_time - clip.start_time,
      transition: clip.transition
    }))

    // 执行合并
    const mergedBlob = await videoMerger.mergeVideos(clips)

    // 下载合并后的视频
    const url = URL.createObjectURL(mergedBlob)
    const a = document.createElement('a')
    a.href = url
    a.download = `merged_video_${Date.now()}.mp4`
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(url)

    ElMessage.success('视频合并完成，已开始下载！')
    mergeDialogVisible.value = false
  } catch (error: any) {
    if (error !== 'cancel') {
      console.error('视频合并失败:', error)
      ElMessage.error(error.message || '视频合并失败')
    }
  } finally {
    merging.value = false
  }
}

// 提交时间线数据到后端进行合成
// 浏览器端FFmpeg合成
const mergeVideoInBrowser = async () => {
  if (timelineClips.value.length === 0) {
    ElMessage.warning('时间线上没有视频片段')
    return
  }


  try {
    await ElMessageBox.confirm(
      '将在浏览器中使用FFmpeg合成视频。\n注意：处理时间较长，且会占用浏览器资源，请勿关闭页面。\n适合少量视频场景（1-5个）。\n是否继续？',
      '浏览器合成视频',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }
    )

    merging.value = true
    mergeProgress.value = 0

    ElMessage.info('开始加载FFmpeg引擎...')

    // 准备剪辑数据
    const clips = timelineClips.value.map(clip => ({
      url: clip.video_url,
      startTime: clip.start_time,
      endTime: clip.end_time
    }))

    // 使用FFmpeg合成
    ElMessage.info('正在合成视频，请稍候...')
    const mergedBlob = await trimAndMergeVideos(clips, (progress) => {
      mergeProgress.value = Math.round(progress)
    })

    // 创建下载链接
    const url = URL.createObjectURL(mergedBlob)
    const link = document.createElement('a')
    link.href = url
    link.download = `episode_${props.episodeId}_merged.mp4`
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    URL.revokeObjectURL(url)

    ElMessage.success('视频合成完成并已下载！')
    emit('merge-completed', 0)
  } catch (error: any) {
    if (error !== 'cancel') {
      ElMessage.error({
        message: `合成失败: ${error.message || '未知错误'}。请检查控制台或尝试服务器合成`,
        duration: 5000
      })
    }
  } finally {
    merging.value = false
    mergeProgress.value = 0
  }
}

// 服务器端合成
const submitTimelineForMerge = async () => {
  if (timelineClips.value.length === 0) {
    ElMessage.warning('时间线上没有视频片段')
    return
  }

  try {
    await ElMessageBox.confirm(
      '将根据时间线编排的顺序和转场效果合成最终视频。\n注意：未生成视频的场景将被跳过，只合成已有视频的场景。\n适合大量场景合成。\n是否继续？',
      '服务器合成视频',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        dangerouslyUseHTMLString: false
      }
    )

    serverMerging.value = true

    // 准备时间线数据
    const timelineData = {
      episode_id: props.episodeId,
      clips: timelineClips.value.map((clip, index) => {
        console.log(`📹 片段 ${index}:`, {
          storyboard_id: clip.storyboard_id,
          transition: clip.transition
        })
        return {
          storyboard_id: String(clip.storyboard_id),
          order: index,
          start_time: clip.start_time,
          end_time: clip.end_time,
          duration: clip.duration,
          transition: clip.transition || { type: 'none', duration: 0 }
        }
      })
    }
    console.log('📤 提交时间线数据:', JSON.stringify(timelineData, null, 2))

    // 调用后端API
    const { dramaAPI } = await import('@/api/drama')
    const result = await dramaAPI.finalizeEpisode(props.episodeId, timelineData)
    
    // 如果有跳过的场景，显示警告
    if (result.warning) {
      ElMessage.warning({
        message: result.warning,
        duration: 5000
      })
    } else {
      ElMessage.success('视频合成任务已提交，正在后台处理...')
    }
    
    emit('merge-completed', result.merge_id || 0)
  } catch (error: any) {
    if (error !== 'cancel') {
      console.error('提交合成任务失败:', error)
      ElMessage.error(error.response?.data?.message || '提交失败')
    }
  } finally {
    serverMerging.value = false
  }
}

// 暴露方法供父组件调用
const updateClipsByStoryboardId = (storyboardId: string | number, newVideoUrl: string) => {
  console.log('=== updateClipsByStoryboardId 调用 ===')
  console.log('目标 storyboard_id:', storyboardId, '类型:', typeof storyboardId)
  console.log('新视频 URL:', newVideoUrl)
  console.log('当前时间线片段数量:', timelineClips.value.length)
  
  let updated = false
  const targetId = String(storyboardId) // 统一转换为字符串进行比较
  
  timelineClips.value.forEach((clip, index) => {
    console.log(`片段 ${index}: storyboard_id=${clip.storyboard_id} (类型: ${typeof clip.storyboard_id})`)
    if (String(clip.storyboard_id) === targetId) {
      console.log(`✅ 匹配成功！更新片段 ${index} 的视频URL`)
      console.log('  旧URL:', clip.video_url)
      console.log('  新URL:', newVideoUrl)
      clip.video_url = newVideoUrl
      updated = true
    }
  })
  
  if (updated) {
    console.log('✅ 时间线视频已更新')
    ElMessage.success('时间线中的视频已自动更新')
  } else {
    console.log('⚠️ 没有找到匹配的时间线片段')
  }
}

defineExpose({
  updateClipsByStoryboardId
})
</script>

<style scoped lang="scss">
.video-timeline-editor {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--bg-primary);
  color: var(--text-primary);

  .editor-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 16px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-primary);

    .toolbar-left {
      display: flex;
      align-items: center;
      gap: 16px;

      .time-display {
        font-family: 'Courier New', monospace;
        font-size: 14px;
        color: var(--text-secondary);
        min-width: 160px;
      }
    }
  }

  .editor-workspace {
    display: flex;
    flex: 1;
    overflow: hidden;

    .preview-panel {
      flex: 0 0 500px;
      display: flex;
      flex-direction: column;
      background: var(--bg-card);
      border: 1px solid var(--border-primary);

      .video-preview {
        flex: 1;
        position: relative;
        background: #000;
        display: flex;
        align-items: center;
        justify-content: center;

        video {
          max-width: 100%;
          max-height: 100%;
          object-fit: contain;
        }

        .preview-overlay {
          position: absolute;
          top: 0;
          left: 0;
          right: 0;
          bottom: 0;
          display: flex;
          align-items: center;
          justify-content: center;
          background: var(--bg-secondary);
        }

        .video-play-overlay {
          position: absolute;
          top: 0;
          left: 0;
          right: 0;
          bottom: 0;
          display: flex;
          align-items: center;
          justify-content: center;
          background: rgba(0, 0, 0, 0.3);
          cursor: pointer;
          transition: opacity 0.3s ease;
          z-index: 5;

          .el-icon {
            color: white;
            filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.5));
          }

          &.hidden {
            opacity: 0;
          }

          &:hover {
            background: rgba(0, 0, 0, 0.4);
          }
        }
        
        .transition-overlay {
          position: absolute;
          top: 0;
          left: 0;
          right: 0;
          bottom: 0;
          pointer-events: none;
          z-index: 10;
        }
        
        // 淡入淡出效果
        .transition-fade.transition-out {
          background: black;
          animation: fadeOut forwards;
        }
        .transition-fade.transition-in {
          background: black;
          animation: fadeIn forwards;
        }
        
        // 黑场过渡
        .transition-fadeblack.transition-out {
          background: black;
          animation: fadeOut forwards;
        }
        .transition-fadeblack.transition-in {
          background: black;
          animation: fadeIn forwards;
        }
        
        // 白场过渡
        .transition-fadewhite.transition-out {
          background: white;
          animation: fadeOut forwards;
        }
        .transition-fadewhite.transition-in {
          background: white;
          animation: fadeIn forwards;
        }
        
        // 左滑
        .transition-slideleft.transition-out {
          background: black;
          animation: slideLeftOut forwards;
        }
        .transition-slideleft.transition-in {
          background: black;
          animation: slideLeftIn forwards;
        }
        
        // 右滑
        .transition-slideright.transition-out {
          background: black;
          animation: slideRightOut forwards;
        }
        .transition-slideright.transition-in {
          background: black;
          animation: slideRightIn forwards;
        }
        
        // 上滑
        .transition-slideup.transition-out {
          background: black;
          animation: slideUpOut forwards;
        }
        .transition-slideup.transition-in {
          background: black;
          animation: slideUpIn forwards;
        }
        
        // 下滑
        .transition-slidedown.transition-out {
          background: black;
          animation: slideDownOut forwards;
        }
        .transition-slidedown.transition-in {
          background: black;
          animation: slideDownIn forwards;
        }
        
        @keyframes fadeOut {
          from { opacity: 0; }
          to { opacity: 1; }
        }
        
        @keyframes fadeIn {
          from { opacity: 1; }
          to { opacity: 0; }
        }
        
        @keyframes slideLeftOut {
          from { transform: translateX(100%); }
          to { transform: translateX(0); }
        }
        
        @keyframes slideLeftIn {
          from { transform: translateX(0); }
          to { transform: translateX(-100%); }
        }
        
        @keyframes slideRightOut {
          from { transform: translateX(-100%); }
          to { transform: translateX(0); }
        }
        
        @keyframes slideRightIn {
          from { transform: translateX(0); }
          to { transform: translateX(100%); }
        }
        
        @keyframes slideUpOut {
          from { transform: translateY(100%); }
          to { transform: translateY(0); }
        }
        
        @keyframes slideUpIn {
          from { transform: translateY(0); }
          to { transform: translateY(-100%); }
        }
        
        @keyframes slideDownOut {
          from { transform: translateY(-100%); }
          to { transform: translateY(0); }
        }
        
        @keyframes slideDownIn {
          from { transform: translateY(0); }
          to { transform: translateY(100%); }
        }
      }

      .preview-controls {
        padding: 12px 16px;
        background: var(--bg-secondary);
        border: 1px solid var(--border-primary);
      }
    }

    .media-library {
      flex: 1;
      display: flex;
      flex-direction: column;
      background: var(--bg-card);
      overflow: hidden;

      .library-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 12px 16px;
        background: var(--bg-secondary);
        border: 1px solid var(--border-primary);

        .header-left {
          display: flex;
          align-items: center;
          gap: 12px;

          h4 {
            margin: 0;
            font-size: 14px;
            font-weight: 500;
            color: var(--text-primary);
          }

          span {
            font-size: 12px;
            color: var(--text-muted);
          }
        }
      }

      .media-grid {
        max-height: 450px;
        overflow-y: auto;
        padding: 12px;
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
        gap: 12px;
        align-content: start;

        // 自定义滚动条样式
        &::-webkit-scrollbar {
          width: 8px;
        }

        &::-webkit-scrollbar-track {
          background: var(--bg-secondary);
          border-radius: 4px;
        }

        &::-webkit-scrollbar-thumb {
          background: var(--border-secondary);
          border-radius: 4px;
          
          &:hover {
            background: var(--border-primary);
          }
        }

        .media-item {
          position: relative;
          background: var(--bg-secondary);
          border-radius: 6px;
          overflow: hidden;
          cursor: move;
          border: 1px solid var(--border-primary);
          transition: all 0.3s;

          &:hover {
            border-color: var(--el-color-primary);
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(0,0,0,0.1);
          }

          .delete-btn {
            position: absolute;
            top: 4px;
            right: 4px;
            z-index: 10;
            opacity: 0;
            transition: opacity 0.3s;
          }

          &:hover .delete-btn {
            opacity: 1;
          }

          .media-thumbnail {
            position: relative;
            width: 100%;
            aspect-ratio: 16/9;
            background: var(--bg-card-hover);
            cursor: pointer;

            video {
              width: 100%;
              height: 100%;
              object-fit: cover;
              pointer-events: none;
            }

            .media-duration {
              position: absolute;
              bottom: 4px;
              right: 4px;
              padding: 2px 6px;
              background: rgba(0, 0, 0, 0.8);
              color: white;
              font-size: 11px;
              border-radius: 3px;
              z-index: 1;
            }

            .media-overlay {
              position: absolute;
              top: 0;
              left: 0;
              right: 0;
              bottom: 0;
              display: flex;
              align-items: center;
              justify-content: center;
              background: rgba(0, 0, 0, 0.6);
              opacity: 0;
              transition: opacity 0.2s;
              z-index: 2;

              .add-to-timeline-btn {
                transform: translateY(10px);
                transition: transform 0.2s;
              }
            }

            &:hover .media-overlay {
              opacity: 1;

              .add-to-timeline-btn {
                transform: translateY(0);
              }
            }
          }

          .media-info {
            padding: 8px;

            .media-title {
              font-size: 12px;
              font-weight: 500;
              color: var(--text-primary);
              margin-bottom: 4px;
            }

            .media-desc {
              font-size: 11px;
              color: var(--text-muted);
              white-space: nowrap;
              overflow: hidden;
              text-overflow: ellipsis;
            }
          }
        }
      }
    }
  }

  .timeline-panel {
    flex: 0 0 280px;
    display: flex;
    flex-direction: column;
    background: var(--bg-card);
    border: 1px solid var(--border-primary);

    .timeline-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 8px 12px;
      background: var(--bg-secondary);
      border: 1px solid var(--border-primary);

      .zoom-controls {
        display: flex;
        align-items: center;
        gap: 8px;

        .zoom-level {
          font-size: 12px;
          color: var(--text-muted);
          min-width: 50px;
          text-align: right;
        }
      }
    }

    .timeline-container {
      flex: 1;
      position: relative;
      overflow-x: auto;
      overflow-y: hidden;
      background: var(--bg-primary);

      .timeline-ruler {
        height: 30px;
        background: var(--bg-card);
        border: 1px solid var(--border-primary);
        position: relative;

        .ruler-tick {
          position: absolute;
          top: 0;
          bottom: 0;

          .tick-mark {
            width: 1px;
            background: var(--border-secondary);

            &.major {
              height: 20px;
              background: var(--border-primary);
            }

            &.minor {
              height: 10px;
              margin-top: 10px;
            }
          }

          .tick-label {
            position: absolute;
            top: 2px;
            left: 4px;
            font-size: 10px;
            color: var(--text-muted);
            font-family: 'Courier New', monospace;
          }
        }
      }

      .playhead {
        position: absolute;
        top: 0;
        bottom: 0;
        z-index: 100;
        pointer-events: none;

        .playhead-line {
          width: 2px;
          height: 100%;
          background: var(--accent);
          box-shadow: 0 0 8px rgba(14, 165, 233, 0.6);
        }

        .playhead-handle {
          position: absolute;
          top: 0;
          left: -6px;
          width: 14px;
          height: 14px;
          background: var(--accent);
          border-radius: 50%;
          border: 2px solid var(--bg-card);
        }
      }

      .timeline-track {
        position: relative;
        height: 80px;
        background: var(--bg-secondary);
        border: 1px solid var(--border-primary);

        .track-label {
          position: absolute;
          left: 0;
          top: 0;
          bottom: 0;
          width: 100px;
          display: flex;
          align-items: center;
          padding-left: 12px;
          font-size: 12px;
          color: var(--text-secondary);
          background: var(--bg-card);
          border: 1px solid var(--border-primary);
          z-index: 50;
        }

        .track-clips {
          position: relative;
          height: 100%;
          padding-left: 100px;

          .track-clip {
            position: absolute;
            top: 8px;
            bottom: 8px;
            background: var(--accent);
            border-radius: 4px;
            border: 2px solid transparent;
            cursor: move;
            transition: all 0.15s;
            overflow: hidden;

            &:hover {
              border-color: var(--accent-hover);
              box-shadow: var(--shadow-md);
            }

            &.selected {
              border-color: var(--accent);
              box-shadow: var(--shadow-glow);
            }

            .clip-content {
              display: flex;
              align-items: center;
              height: 100%;
              padding: 4px 8px;
              gap: 8px;

              .clip-thumbnail {
                width: 60px;
                height: 100%;
                background: var(--bg-card-hover);
                border-radius: 3px;
                overflow: hidden;
                flex-shrink: 0;

                video {
                  width: 100%;
                  height: 100%;
                  object-fit: cover;
                  pointer-events: none;
                }
              }

              .clip-info {
                flex: 1;
                min-width: 0;

                .clip-title {
                  font-size: 11px;
                  font-weight: 500;
                  color: var(--text-inverse);
                  margin-bottom: 2px;
                  white-space: nowrap;
                  overflow: hidden;
                  text-overflow: ellipsis;
                }

                .clip-duration {
                  font-size: 10px;
                  color: var(--text-inverse);
                  opacity: 0.8;
                }
              }
            }

            .clip-resize-left,
            .clip-resize-right {
              position: absolute;
              top: 0;
              bottom: 0;
              width: 8px;
              cursor: ew-resize;
              z-index: 10;

              &:hover {
                background: rgba(52, 152, 219, 0.3);
              }
            }

            .clip-resize-left {
              left: 0;
            }

            .clip-resize-right {
              right: 0;
            }

            .clip-remove {
              position: absolute;
              top: 4px;
              right: 4px;
              width: 18px;
              height: 18px;
              background: rgba(0, 0, 0, 0.6);
              border-radius: 50%;
              display: flex;
              align-items: center;
              justify-content: center;
              cursor: pointer;
              opacity: 0;
              transition: opacity 0.2s;

              &:hover {
                background: var(--error);
              }
            }

            &:hover .clip-remove {
              opacity: 1;
            }
          }
          
          .transition-indicator {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            width: 30px;
            height: 30px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            border-radius: 50%;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            z-index: 60;
            border: 2px solid #1e1e1e;
            box-shadow: 0 2px 8px rgba(102, 126, 234, 0.4);
            transition: all 0.2s;

            &:hover {
              transform: translateY(-50%) scale(1.2);
              box-shadow: 0 4px 12px rgba(102, 126, 234, 0.6);
            }

            .el-icon {
              font-size: 14px;
              color: white;
            }

            .transition-label {
              position: absolute;
              top: 100%;
              margin-top: 4px;
              font-size: 10px;
              color: var(--text-secondary);
              white-space: nowrap;
              background: rgba(0, 0, 0, 0.8);
              padding: 2px 6px;
              border-radius: 3px;
              pointer-events: none;
              opacity: 0;
              transition: opacity 0.2s;
            }

            &:hover .transition-label {
              opacity: 1;
            }
          }
        }
      }

      // 音频轨道特殊样式
      .audio-track {
        .track-label {
          display: flex;
          align-items: center;
          justify-content: space-between;
          padding-right: 8px;

          .el-button {
            color: var(--text-muted);
            
            &:hover {
              color: var(--accent);
            }
          }
        }

        .audio-clip {
          background: #7c3aed;

          &:hover {
            border-color: #a78bfa;
            box-shadow: var(--shadow-md);
          }

          &.selected {
            border-color: #8b5cf6;
            box-shadow: var(--shadow-glow);
          }

          .audio-waveform {
            width: 60px;
            height: 100%;
            background: linear-gradient(135deg, #8b5cf6 0%, var(--accent) 100%);
            border-radius: 3px;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-shrink: 0;

            .el-icon {
              font-size: 24px;
              color: rgba(255, 255, 255, 0.8);
            }
          }
        }
      }
    }
  }

  .merge-progress-container {
    padding: 20px 0;

    .progress-info {
      margin-bottom: 20px;

      .progress-phase {
        margin-bottom: 8px;
      }

      .progress-message {
        font-size: 14px;
        color: var(--text-secondary);
        font-weight: 500;
      }
    }

    .progress-tips {
      margin-top: 20px;
      padding: 12px;
      background: var(--bg-secondary);
      border-radius: 6px;

      p {
        margin: 0;
        display: flex;
        align-items: center;
        gap: 8px;
        font-size: 13px;
        color: var(--text-secondary);

        .el-icon {
          font-size: 16px;
        }
      }
    }
  }
}
</style>
