<script setup lang="ts">
interface Props {
  src: string
  type?: 'mp4' | 'webm'
  poster?: string
  play?: boolean
  loop?: boolean
  bordered?: boolean
  class?: string
  /**
   * 비디오 데이터 로딩 시점
   * - none: 재생 전까지 로드 안 함 (가장 절약)
   * - metadata: 길이·크기 등 메타만 로드
   * - auto: 재생에 맞게 미리 로드 (autoplay 시 권장)
   */
  preload?: 'none' | 'metadata' | 'auto'
}

const props = withDefaults(defineProps<Props>(), {
  type: 'mp4',
  play: true,
  loop: true,
  bordered: true,
})

const effectivePreload = computed(
  () => props.preload ?? (props.play ? 'auto' : 'none')
)

const videoRef = ref<HTMLVideoElement | null>(null)
const pauseTimer = ref<ReturnType<typeof setTimeout> | null>(null)

const clearPauseTimer = () => {
  if (pauseTimer.value) {
    clearTimeout(pauseTimer.value)
    pauseTimer.value = null
  }
}

const playVideo = async () => {
  if (!videoRef.value) return

  clearPauseTimer()

  try {
    await videoRef.value.play()
  } catch (e) {
    console.warn('Video play failed:', e)
  }
}

const pauseVideo = () => {
  if (!videoRef.value) return

  clearPauseTimer()

  pauseTimer.value = setTimeout(() => {
    if (videoRef.value) {
      videoRef.value.pause()
      videoRef.value.currentTime = 0
    }
    pauseTimer.value = null
  }, 500)
}

const waitForCanPlay = () =>
  new Promise<void>(resolve => {
    if (!videoRef.value) return resolve()
    videoRef.value.addEventListener('canplay', () => resolve(), { once: true })
  })

const reloadVideo = async () => {
  if (!videoRef.value) return

  clearPauseTimer()
  videoRef.value.currentTime = 0
  videoRef.value.load()

  if (props.play) {
    await waitForCanPlay()
    await playVideo()
  }
}

const syncPlayState = (shouldPlay: boolean) => {
  if (shouldPlay) {
    void playVideo()
  } else {
    pauseVideo()
  }
}

// src 변경 시 비디오 다시 로드
watch(
  () => props.src,
  () => {
    void reloadVideo()
  }
)

// play 상태 변경 시 재생/일시정지
watch(
  () => props.play,
  shouldPlay => {
    syncPlayState(!!shouldPlay)
  }
)

onMounted(() => {
  nextTick(async () => {
    if (props.play) {
      await waitForCanPlay()
      await playVideo()
    }
  })
})

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

<template>
  <div
    v-if="props.src"
    :class="['video-box', { 'has-bordered': props.bordered }, props.class]"
  >
    <video
      ref="videoRef"
      :poster="props.poster"
      :loop="props.loop"
      :autoplay="props.play"
      :preload="effectivePreload"
      muted
      playsinline
      webkit-playsinline
    >
      <source :src="props.src" :type="`video/${props.type}`" />
    </video>
  </div>
</template>

<style scoped>
.video-box {
  @apply overflow-hidden;
}
.video-box.has-bordered {
  @apply relative rounded-[4px] md:rounded-[8px]
  after:content-[''] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:border after:border-white after:opacity-10 after:rounded-[4px] after:md:rounded-[8px];
}
.video-box video {
  @apply absolute top-0 left-0 w-full h-full object-cover;
}
</style>
