<!-- src/components/TimelineSlider.vue -->
<template>
  <div class="timeline-slider" ref="sliderRef" @touchstart.prevent
    @pointerdown.prevent="onPointerDown">
    <!-- 底部轨道 -->
    <div class="slider-track" :style="trackStyle">
      <!-- 当 mode 为 segments 时，根据 segments 数据渲染各段颜色 -->
      <template v-if="mode === 'segments' && segments.length">
        <div v-for="(segment, index) in segments" :key="index"
          class="slider-segment" :style="getSegmentStyle(segment)"></div>
      </template>
      <!-- 当 mode 为 ticks 时，渲染刻度标记 -->
      <template v-if="mode === 'ticks' && markers.length">
        <div v-for="(marker, index) in markers" :key="index"
          class="slider-marker" :style="getMarkerStyle(marker)"></div>
      </template>
    </div>

    <!-- 可拖动的滑块 -->
    <div class="slider-handle" :style="handleStyle" @touchstart.prevent
      @pointerdown.prevent="onPointerDown">
      <!-- 拖动时显示 tooltip -->
      <div v-if="showTooltip" class="slider-tooltip" :style="tooltipStyle">
        {{ formattedValue }}
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue';
import { format } from 'date-fns';

interface Segment {
  start: number;
  end: number;
  active: boolean;
}

interface Marker {
  time: number;
  label?: string;
  active?: boolean;
}

const props = defineProps({
  minTime: { type: Number, required: true },
  maxTime: { type: Number, required: true },
  modelValue: { type: Number, required: true },
  mode: { type: String, default: 'default' }, // 可传 'segments' 或 'ticks'
  segments: { type: Array as () => Segment[], default: () => [] },
  markers: { type: Array as () => Marker[], default: () => [] }
});
const emit = defineEmits(['update:modelValue', 'change']);

const sliderRef = ref<HTMLElement | null>(null);
const dragging = ref(false);
const internalValue = ref(props.modelValue);
const showTooltip = ref(false);

watch(() => props.modelValue, (newVal) => {
  internalValue.value = newVal;
});
watch(internalValue, (newVal) => {
  emit('update:modelValue', newVal);
});

// 格式化当前值显示为时间字符串
const formattedValue = computed(() => {
  return format(new Date(internalValue.value), 'HH:mm:ss');
});
// 当前值在整个区间内的百分比
const percentage = computed(() => {
  return ((internalValue.value - props.minTime) / (props.maxTime - props.minTime)) * 100;
});
const handleStyle = computed(() => {
  return {
    position: 'absolute' as any,
    left: `${percentage.value}%`,
    transform: 'translate(-50%, -50%)',
    top: '50%',
    width: '20px',
    height: '20px',
    borderRadius: '50%',
    backgroundColor: '#4ADE80', // 绿色
    border: '2px solid white',
    boxShadow: '0 0 2px rgba(0,0,0,0.5)',
    zIndex: 2,
    cursor: 'pointer'
  };
});
const trackStyle = computed(() => {
  return {
    position: 'absolute' as any,
    top: '50%',
    left: 0,
    right: 0,
    height: '6px',
    backgroundColor: '#E5E7EB', // 灰色
    transform: 'translateY(-50%)',
    borderRadius: '3px'
  };
});
// 根据每个 segment 计算其位置及宽度
const getSegmentStyle = (segment: Segment) => {
  const startPercent = ((segment.start - props.minTime) / (props.maxTime - props.minTime)) * 100;
  const endPercent = ((segment.end - props.minTime) / (props.maxTime - props.minTime)) * 100;
  const widthPercent = endPercent - startPercent;
  return {
    position: 'absolute' as any,
    left: `${startPercent}%`,
    width: `${widthPercent}%`,
    height: '100%',
    backgroundColor: segment.active ? '#4ADE80' : '#E5E7EB',
    borderLeft: '1px solid #E5E7EB',
    borderRight: '1px solid #E5E7EB',
  };
};
// 根据 marker 计算其位置
const getMarkerStyle = (marker: Marker) => {
  const pos = ((marker.time - props.minTime) / (props.maxTime - props.minTime)) * 100;
  return {
    position: 'absolute' as any,
    left: `${pos}%`,
    top: '50%',
    width: '2px',
    height: '100%',
    backgroundColor: marker.active ? '#4ADE80' : '#9CA3AF',
    transform: 'translate(-50%, -50%)'
  };
};

const tooltipStyle = computed(() => {
  return {
    position: 'absolute' as any,
    bottom: '100%', // 显示在滑块上方
    left: '50%',
    transform: 'translateX(-50%)',
    marginBottom: '8px',
    padding: '4px 8px',
    backgroundColor: 'rgba(0, 0, 0, 0.7)',
    color: 'white',
    borderRadius: '4px',
    fontSize: '12px',
    whiteSpace: 'nowrap'
  };
});

const pointerMoveHandler = (event: PointerEvent) => {
  if (!dragging.value || !sliderRef.value) return;
  const rect = sliderRef.value.getBoundingClientRect();
  let x = event.clientX - rect.left;
  x = Math.max(0, Math.min(x, rect.width));
  const newValue = props.minTime + (x / rect.width) * (props.maxTime - props.minTime);
  internalValue.value = newValue;
};

const pointerUpHandler = () => {
  dragging.value = false;
  showTooltip.value = false;
  window.removeEventListener('pointermove', pointerMoveHandler);
  window.removeEventListener('pointerup', pointerUpHandler);

  // 根据当前模式吸附到最近的点上
  const snapped = getSnapValue(internalValue.value);
  internalValue.value = snapped;
  emit('change', snapped);
};

/**
 * 根据当前的 internalValue 计算吸附（snap）后的值：
 * - 若 mode 为 'ticks' 且 markers 不为空，则吸附到最近的 marker.time；
 * - 若 mode 为 'segments' 且存在 active 的 segment，则吸附到最近 active segment 的中点；
 * - 否则直接返回当前值。
 */
const getSnapValue = (value: number): number => {
  if (props.mode === 'ticks' && props.markers.length > 0) {
    let closest = props.markers[0].time;
    let minDiff = Math.abs(value - props.markers[0].time);
    for (const marker of props.markers) {
      const diff = Math.abs(value - marker.time);
      if (diff < minDiff) {
        minDiff = diff;
        closest = marker.time;
      }
    }
    return closest;
  } else if (props.mode === 'segments' && props.segments.length > 0) {
    // 遍历所有 active 的 segments，计算其 start 和 end 的中点，并返回与 value 最近的那个中点
    let closestMidpoint: number | null = null;
    let minDiff = Infinity;
    for (const segment of props.segments) {
      if (segment.active) {
        const midpoint = (segment.start + segment.end) / 2;
        const diff = Math.abs(value - midpoint);
        if (diff < minDiff) {
          minDiff = diff;
          closestMidpoint = midpoint;
        }
      }
    }
    if (closestMidpoint !== null) {
      return closestMidpoint;
    }
  }
  return value;
};


const onPointerDown = (event: PointerEvent) => {
  event.stopPropagation();
  dragging.value = true;
  showTooltip.value = true;
  window.addEventListener('pointermove', pointerMoveHandler);
  window.addEventListener('pointerup', pointerUpHandler);
  if (!dragging.value || !sliderRef.value) return;
  const rect = sliderRef.value.getBoundingClientRect();
  let x = event.clientX - rect.left;
  x = Math.max(0, Math.min(x, rect.width));
  const newValue = props.minTime + (x / rect.width) * (props.maxTime - props.minTime);
  internalValue.value = newValue;
};

onMounted(() => {
  // 初始化操作（如有需要）……
});
</script>

<style scoped>
.timeline-slider {
  position: relative;
  height: 40px;
  user-select: none;
  touch-action: none;
}
</style>