<script setup>
const props = defineProps({
  /** 비디오 파일 URL */
  src: {
    type: String,
    required: true
  },
  /** 접근성 대체 텍스트 */
  alt: {
    type: String,
    default: '비디오 썸네일'
  }
})

const videoRef = ref(null)
const canvasRef = ref(null)
const thumbnailUrl = ref('')
const failed = ref(false)

/**
 * 비디오 프레임을 캔버스 이미지로 변환한다.
 * @returns {void}
 */
const captureVideoFrame = () => {
  const video = videoRef.value
  const canvas = canvasRef.value

  if (!video || !canvas || !video.videoWidth || !video.videoHeight) {
    failed.value = true
    return
  }

  canvas.width = video.videoWidth
  canvas.height = video.videoHeight

  const context = canvas.getContext('2d')
  if (!context) {
    failed.value = true
    return
  }

  try {
    context.drawImage(video, 0, 0, canvas.width, canvas.height)
    thumbnailUrl.value = canvas.toDataURL('image/jpeg', 0.78)
  } catch {
    failed.value = true
  }
}

/**
 * 메타데이터 로드 후 초반 프레임으로 이동한다.
 * @returns {void}
 */
const seekPreviewFrame = () => {
  const video = videoRef.value
  if (!video) {
    failed.value = true
    return
  }

  const duration = Number.isFinite(video.duration) ? video.duration : 0
  const targetTime = duration > 1 ? Math.min(1, duration * 0.1) : 0

  try {
    video.currentTime = targetTime
  } catch {
    captureVideoFrame()
  }
}
</script>

<template>
  <span class="admin-media-video-thumbnail relative block aspect-square w-full overflow-hidden bg-surface">
    <img
      v-if="thumbnailUrl"
      class="admin-media-video-thumbnail__image h-full w-full object-cover"
      :src="thumbnailUrl"
      :alt="alt"
      loading="lazy"
    >
    <span
      v-else
      class="admin-media-video-thumbnail__fallback flex h-full w-full items-center justify-center text-xs font-bold uppercase tracking-[0.18em] text-muted"
    >
      video
    </span>
    <span class="admin-media-video-thumbnail__badge absolute bottom-1.5 left-1.5 rounded bg-black/70 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-[0.12em] text-white">
      video
    </span>
    <video
      ref="videoRef"
      class="hidden"
      :src="src"
      muted
      playsinline
      preload="metadata"
      crossorigin="anonymous"
      @loadedmetadata="seekPreviewFrame"
      @seeked="captureVideoFrame"
      @error="failed = true"
    />
    <canvas ref="canvasRef" class="hidden" aria-hidden="true" />
    <span v-if="failed && !thumbnailUrl" class="sr-only">
      {{ alt }}
    </span>
  </span>
</template>
