/**
 * PPT 预览演示交互：分步揭示、翻页、全屏、键盘与滚轮
 */
import { computed, onMounted, onUnmounted, ref, watchEffect, type Ref } from 'vue'
import { getSlideStepCount, isMediaInteractionTarget, type PptSlide } from '../utils/articlePptSlides'

export type SlideDirection = 'forward' | 'backward' | 'none'

const WHEEL_THROTTLE_MS = 300

export function usePptPresentation(slides: Ref<PptSlide[]>, containerRef: Ref<HTMLElement | null>) {
  const currentIndex = ref(0)
  const currentStep = ref(0)
  const isFullscreen = ref(false)
  const slideDirection = ref<SlideDirection>('none')

  const totalSlides = computed(() => slides.value.length)

  const currentSlide = computed(() => slides.value[currentIndex.value])

  const maxStep = computed(() => {
    const slide = currentSlide.value
    return slide ? getSlideStepCount(slide) - 1 : 0
  })

  const totalSteps = computed(() => maxStep.value + 1)

  const goToSlide = (index: number) => {
    if (index < 0 || index >= slides.value.length) return
    slideDirection.value = index > currentIndex.value ? 'forward' : index < currentIndex.value ? 'backward' : 'none'
    currentIndex.value = index
    currentStep.value = 0
  }

  const advance = () => {
    if (currentStep.value < maxStep.value) {
      slideDirection.value = 'forward'
      currentStep.value += 1
      return
    }
    if (currentIndex.value < slides.value.length - 1) {
      slideDirection.value = 'forward'
      currentIndex.value += 1
      currentStep.value = 0
    }
  }

  const retreat = () => {
    if (currentStep.value > 0) {
      slideDirection.value = 'backward'
      currentStep.value -= 1
      return
    }
    if (currentIndex.value > 0) {
      slideDirection.value = 'backward'
      const newIndex = currentIndex.value - 1
      currentIndex.value = newIndex
      const prevSlide = slides.value[newIndex]
      currentStep.value = prevSlide ? getSlideStepCount(prevSlide) - 1 : 0
    }
  }

  const syncFullscreenState = () => {
    isFullscreen.value = document.fullscreenElement === containerRef.value
  }

  const toggleFullscreen = async () => {
    const el = containerRef.value
    if (!el) return

    try {
      if (document.fullscreenElement === el) {
        await document.exitFullscreen()
      } else {
        await el.requestFullscreen()
      }
    } catch (err) {
      console.error('Fullscreen failed:', err)
    }
  }

  const handleKeydown = (e: KeyboardEvent) => {
    const target = e.target as HTMLElement | null
    if (target?.tagName === 'INPUT' || target?.tagName === 'TEXTAREA') return
    if (isMediaInteractionTarget(target) || isMediaInteractionTarget(document.activeElement)) return

    switch (e.key) {
      case 'ArrowRight':
      case 'ArrowDown':
      case ' ':
      case 'PageDown':
        e.preventDefault()
        advance()
        break
      case 'ArrowLeft':
      case 'ArrowUp':
      case 'PageUp':
        e.preventDefault()
        retreat()
        break
      case 'Home':
        e.preventDefault()
        goToSlide(0)
        break
      case 'End':
        e.preventDefault()
        goToSlide(slides.value.length - 1)
        break
      case 'f':
      case 'F':
        e.preventDefault()
        void toggleFullscreen()
        break
      default:
        break
    }
  }

  let wheelTarget: HTMLElement | null = null
  let lastWheelAt = 0

  const handleWheel = (e: WheelEvent) => {
    if (isMediaInteractionTarget(e.target)) return
    if (Math.abs(e.deltaY) < 10) return
    const now = Date.now()
    if (now - lastWheelAt < WHEEL_THROTTLE_MS) return
    lastWheelAt = now
    e.preventDefault()
    if (e.deltaY > 0) advance()
    else retreat()
  }

  watchEffect((onCleanup) => {
    const el = containerRef.value
    if (!el || el === wheelTarget) return
    if (wheelTarget) wheelTarget.removeEventListener('wheel', handleWheel)
    wheelTarget = el
    el.addEventListener('wheel', handleWheel, { passive: false })
    onCleanup(() => {
      el.removeEventListener('wheel', handleWheel)
      if (wheelTarget === el) wheelTarget = null
    })
  })

  onMounted(() => {
    document.addEventListener('keydown', handleKeydown)
    document.addEventListener('fullscreenchange', syncFullscreenState)
  })

  onUnmounted(() => {
    document.removeEventListener('keydown', handleKeydown)
    document.removeEventListener('fullscreenchange', syncFullscreenState)
    if (wheelTarget) wheelTarget.removeEventListener('wheel', handleWheel)
    if (document.fullscreenElement === containerRef.value) {
      void document.exitFullscreen()
    }
  })

  return {
    currentIndex,
    currentStep,
    totalSlides,
    totalSteps,
    maxStep,
    slideDirection,
    isFullscreen,
    goToSlide,
    advance,
    retreat,
    toggleFullscreen,
  }
}
