<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'

const props = defineProps<{
  frames: Array<{ seq: number; timestamp: number; jpeg_b64: string }>
  currentIndex: number
  selectionStart: number
  selectionEnd: number
}>()

const emit = defineEmits<{
  'frame-click': [index: number]
  'selection-change': [start: number, end: number]
}>()

const stripEl = ref<HTMLElement | null>(null)

// --- Drag handle logic ---
type DragTarget = 'start' | 'end' | null
const dragging = ref<DragTarget>(null)

function onHandleMousedown(target: DragTarget, e: MouseEvent) {
  dragging.value = target
  e.preventDefault()
}

function onMousemove(e: MouseEvent) {
  if (!dragging.value || !stripEl.value) return
  const rect = stripEl.value.getBoundingClientRect()
  const x = e.clientX - rect.left
  const ratio = Math.max(0, Math.min(1, x / rect.width))
  const idx = Math.round(ratio * (props.frames.length - 1))

  if (dragging.value === 'start') {
    const newStart = Math.min(idx, props.selectionEnd)
    emit('selection-change', newStart, props.selectionEnd)
  } else {
    const newEnd = Math.max(idx, props.selectionStart)
    emit('selection-change', props.selectionStart, newEnd)
  }
}

function onMouseup() {
  dragging.value = null
}

onMounted(() => {
  window.addEventListener('mousemove', onMousemove)
  window.addEventListener('mouseup', onMouseup)
})
onUnmounted(() => {
  window.removeEventListener('mousemove', onMousemove)
  window.removeEventListener('mouseup', onMouseup)
})

// Handle positions as % of strip width
const startPct = computed(() => {
  if (props.frames.length <= 1) return 0
  return (props.selectionStart / (props.frames.length - 1)) * 100
})
const endPct = computed(() => {
  if (props.frames.length <= 1) return 100
  return (props.selectionEnd / (props.frames.length - 1)) * 100
})

function isInSelection(idx: number) {
  return idx >= props.selectionStart && idx <= props.selectionEnd
}

// --- Scrub slider ---
function onScrub(e: Event) {
  const val = Number((e.target as HTMLInputElement).value)
  emit('frame-click', val)
}
</script>

<template>
  <div class="frame-strip" ref="stripEl">
    <!-- Thumbnails -->
    <div class="thumbs">
      <div
        v-for="(frame, idx) in frames"
        :key="frame.seq"
        class="thumb"
        :class="{
          current: idx === currentIndex,
          dimmed: !isInSelection(idx),
        }"
        @click="emit('frame-click', idx)"
        :title="`Frame ${frame.seq} · ${frame.timestamp.toFixed(2)}s`"
      >
        <img :src="`data:image/jpeg;base64,${frame.jpeg_b64}`" />
      </div>
    </div>

    <!-- Scrub slider -->
    <div class="scrub-row">
      <input
        type="range"
        class="scrub-slider"
        :min="0"
        :max="frames.length - 1"
        :value="currentIndex"
        @input="onScrub"
      />
      <span class="scrub-label">{{ currentIndex + 1 }}/{{ frames.length }}</span>
    </div>

    <!-- Selection handles -->
    <div class="handles">
      <div
        class="handle handle-start"
        :style="{ left: startPct + '%' }"
        @mousedown="onHandleMousedown('start', $event)"
        title="Drag to set selection start"
      />
      <div
        class="handle handle-end"
        :style="{ left: endPct + '%' }"
        @mousedown="onHandleMousedown('end', $event)"
        title="Drag to set selection end"
      />
      <div
        class="selection-range"
        :style="{ left: startPct + '%', width: (endPct - startPct) + '%' }"
      />
    </div>
  </div>
</template>

<style scoped>
.frame-strip {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--surface-1);
  border-top: var(--panel-border);
  user-select: none;
}

.thumbs {
  display: flex;
  flex-direction: row;
  gap: 2px;
  padding: 4px 6px 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.thumbs::-webkit-scrollbar { display: none; }

.thumb {
  flex-shrink: 0;
  width: 80px;
  height: 50px;
  border: 2px solid transparent;
  border-radius: 2px;
  overflow: hidden;
  cursor: pointer;
  transition: border-color 0.1s, opacity 0.15s;
}

.thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.thumb.current {
  border-color: #00bcd4;
}

.thumb.dimmed {
  opacity: 0.35;
}

.thumb:hover:not(.current) {
  border-color: var(--surface-3);
}

/* Scrub slider row */
.scrub-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 6px;
}

.scrub-slider {
  -webkit-appearance: none;
  appearance: none;
  flex: 1;
  height: 4px;
  background: var(--surface-3);
  border-radius: 2px;
  outline: none;
}

.scrub-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #00bcd4;
  cursor: pointer;
}

.scrub-slider::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #00bcd4;
  cursor: pointer;
  border: none;
}

.scrub-label {
  font-size: 9px;
  color: var(--text-dim);
  font-family: var(--font-mono);
  min-width: 30px;
  text-align: right;
}

/* Handle track area */
.handles {
  position: relative;
  height: 14px;
  margin: 0 6px;
}

.selection-range {
  position: absolute;
  top: 5px;
  height: 4px;
  background: #00bcd4;
  opacity: 0.35;
  pointer-events: none;
}

.handle {
  position: absolute;
  top: 0;
  width: 10px;
  height: 14px;
  transform: translateX(-50%);
  cursor: ew-resize;
  z-index: 2;
}

.handle::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 2px;
  transform: translateX(-50%);
  width: 3px;
  height: 10px;
  background: #00bcd4;
  border-radius: 2px;
}
</style>
