<template>
  <div class="video-player-wrapper" ref="wrapperRef">
    <!-- Cloudflare Stream Player (iframe 模式) -->
    <template v-if="playerType === 'cloudflare'">
      <iframe
        :src="cloudflareIframeSrc"
        class="cloudflare-iframe"
        allow="accelerometer; gyroscope; autoplay; encrypted-media; picture-in-picture"
        allowfullscreen
      />
    </template>

    <!-- Cloudflare Stream WebRTC (WHEP) Player -->
    <template v-else-if="playerType === 'cloudflare-webrtc'">
      <video
        ref="videoRef"
        class="video-element"
        :controls="controls"
        :autoplay="autoplay"
        :muted="muted"
        playsinline
      />
      <!-- WebRTC 连接状态 -->
      <div v-if="cfWebrtcStatus !== 'connected'" class="webrtc-status">
        <span v-if="cfWebrtcStatus === 'connecting'" class="status-connecting">WebRTC 连接中...</span>
        <span v-else-if="cfWebrtcStatus === 'failed'" class="status-failed">WebRTC 连接失败</span>
        <span v-else class="status-idle">等待连接</span>
      </div>
    </template>

    <!-- WebRTC Player (go2rtc) -->
    <template v-else-if="playerType === 'webrtc'">
      <video
        ref="videoRef"
        class="video-element"
        :controls="controls"
        :autoplay="autoplay"
        :muted="muted"
        playsinline
      />
      <!-- WebRTC 连接状态 -->
      <div v-if="webrtcStatus !== 'connected'" class="webrtc-status">
        <span v-if="webrtcStatus === 'connecting'" class="status-connecting">连接中...</span>
        <span v-else-if="webrtcStatus === 'failed'" class="status-failed">连接失败</span>
        <span v-else class="status-idle">等待连接</span>
      </div>
    </template>

    <!-- HLS.js Player -->
    <template v-else-if="playerType === 'hls'">
      <video
        ref="videoRef"
        class="video-element"
        :controls="controls"
        :autoplay="autoplay"
        :muted="muted"
        :loop="loop"
        :poster="poster"
        playsinline
      />
    </template>

    <!-- Native Video (MP4/WebM) -->
    <template v-else>
      <video
        ref="videoRef"
        class="video-element"
        :src="src"
        :controls="controls"
        :autoplay="autoplay"
        :muted="muted"
        :loop="loop"
        :poster="poster"
        playsinline
      />
    </template>
  </div>
</template>

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

interface Props {
  src?: string // 视频源地址
  videoId?: string // Cloudflare Stream video ID
  customerDomain?: string // Cloudflare 自定义域名
  playerType?: 'cloudflare' | 'cloudflare-webrtc' | 'hls' | 'native' | 'webrtc'
  useIframe?: boolean // Cloudflare 是否使用 iframe
  controls?: boolean
  autoplay?: boolean
  muted?: boolean
  loop?: boolean
  poster?: string
  preload?: 'auto' | 'metadata' | 'none'
  // WebRTC 配置 (go2rtc)
  go2rtcUrl?: string // go2rtc 服务地址，如 http://localhost:1984
  streamName?: string // 流名称，如 camera1
}

const props = withDefaults(defineProps<Props>(), {
  playerType: 'native',
  useIframe: true,
  controls: true,
  autoplay: false,
  muted: true,
  loop: false,
  preload: 'metadata'
})

const emit = defineEmits<{
  play: []
  pause: []
  ended: []
  error: [error: any]
  timeupdate: [currentTime: number]
}>()

const wrapperRef = ref<HTMLElement>()
const videoRef = ref<HTMLVideoElement>()

let hlsInstance: any = null
let peerConnection: RTCPeerConnection | null = null
let cfPeerConnection: RTCPeerConnection | null = null
const webrtcStatus = ref<'idle' | 'connecting' | 'connected' | 'failed'>('idle')
const cfWebrtcStatus = ref<'idle' | 'connecting' | 'connected' | 'failed'>('idle')

// Cloudflare Stream iframe URL
const cloudflareIframeSrc = computed(() => {
  if (!props.videoId) return ''
  const domain = props.customerDomain || 'customer-xxx.cloudflarestream.com'
  const params = new URLSearchParams()
  if (props.autoplay) params.set('autoplay', 'true')
  if (props.muted) params.set('muted', 'true')
  if (props.loop) params.set('loop', 'true')
  if (props.preload) params.set('preload', props.preload)
  const queryString = params.toString()
  return `https://${domain}/${props.videoId}/iframe${queryString ? `?${queryString}` : ''}`
})

// Cloudflare Stream WebRTC (WHEP) URL
const cloudflareWebRTCUrl = computed(() => {
  if (!props.videoId) return ''
  const domain = props.customerDomain || 'customer-xxx.cloudflarestream.com'
  return `https://${domain}/${props.videoId}/webRTC/play`
})

// 初始化 HLS.js
async function initHls() {
  if (!videoRef.value || !props.src) return

  // 动态导入 hls.js
  const { default: Hls } = await import('hls.js')

  if (Hls.isSupported()) {
    hlsInstance = new Hls({
      debug: false,
      enableWorker: true,
      lowLatencyMode: true
    })

    hlsInstance.loadSource(props.src)
    hlsInstance.attachMedia(videoRef.value)

    hlsInstance.on(Hls.Events.MANIFEST_PARSED, () => {
      if (props.autoplay) {
        videoRef.value?.play()
      }
    })

    hlsInstance.on(Hls.Events.ERROR, (_event: any, data: any) => {
      if (data.fatal) {
        emit('error', data)
        switch (data.type) {
          case Hls.ErrorTypes.NETWORK_ERROR:
            hlsInstance.startLoad()
            break
          case Hls.ErrorTypes.MEDIA_ERROR:
            hlsInstance.recoverMediaError()
            break
          default:
            destroyHls()
            break
        }
      }
    })
  } else if (videoRef.value.canPlayType('application/vnd.apple.mpegurl')) {
    // Safari 原生支持 HLS
    videoRef.value.src = props.src
    if (props.autoplay) {
      videoRef.value.play()
    }
  }

  // 绑定事件
  bindVideoEvents()
}

function bindVideoEvents() {
  if (!videoRef.value) return

  videoRef.value.addEventListener('play', () => emit('play'))
  videoRef.value.addEventListener('pause', () => emit('pause'))
  videoRef.value.addEventListener('ended', () => emit('ended'))
  videoRef.value.addEventListener('error', (e) => emit('error', e))
  videoRef.value.addEventListener('timeupdate', () => {
    emit('timeupdate', videoRef.value?.currentTime || 0)
  })
}

function destroyHls() {
  if (hlsInstance) {
    hlsInstance.destroy()
    hlsInstance = null
  }
}

// 初始化 Cloudflare WebRTC (WHEP)
async function initCloudflareWebRTC() {
  if (!videoRef.value || !props.videoId) return

  cfWebrtcStatus.value = 'connecting'

  try {
    const whepUrl = cloudflareWebRTCUrl.value
    console.log('Cloudflare WebRTC URL:', whepUrl)

    // 创建 RTCPeerConnection
    cfPeerConnection = new RTCPeerConnection({
      iceServers: [{ urls: 'stun:stun.cloudflare.com:3478' }, { urls: 'stun:stun.l.google.com:19302' }],
      bundlePolicy: 'max-bundle'
    })

    // 监听远程流
    cfPeerConnection.ontrack = (event) => {
      console.log('Cloudflare WebRTC: received track', event.track.kind)
      if (videoRef.value && event.streams[0]) {
        videoRef.value.srcObject = event.streams[0]
        cfWebrtcStatus.value = 'connected'
        if (props.autoplay) {
          videoRef.value.play().catch((e) => console.warn('Autoplay failed:', e))
        }
      }
    }

    // 监听连接状态
    cfPeerConnection.oniceconnectionstatechange = () => {
      if (!cfPeerConnection) return
      const state = cfPeerConnection.iceConnectionState
      console.log('Cloudflare WebRTC ICE state:', state)
      if (state === 'connected' || state === 'completed') {
        cfWebrtcStatus.value = 'connected'
      } else if (state === 'failed' || state === 'disconnected') {
        cfWebrtcStatus.value = 'failed'
        emit('error', { type: 'cloudflare-webrtc', message: `ICE connection ${state}` })
      }
    }

    // 添加音视频收发器
    cfPeerConnection.addTransceiver('video', { direction: 'recvonly' })
    cfPeerConnection.addTransceiver('audio', { direction: 'recvonly' })

    // 创建 Offer
    const offer = await cfPeerConnection.createOffer()
    await cfPeerConnection.setLocalDescription(offer)

    // 等待 ICE gathering 完成或超时
    await new Promise<void>((resolve) => {
      if (cfPeerConnection?.iceGatheringState === 'complete') {
        resolve()
      } else {
        const timeout = setTimeout(resolve, 2000)
        cfPeerConnection!.onicegatheringstatechange = () => {
          if (cfPeerConnection?.iceGatheringState === 'complete') {
            clearTimeout(timeout)
            resolve()
          }
        }
      }
    })

    // 发送 Offer 到 Cloudflare WHEP 端点
    const response = await fetch(whepUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/sdp'
      },
      body: cfPeerConnection.localDescription?.sdp
    })

    if (!response.ok) {
      const errorText = await response.text()
      throw new Error(`WHEP request failed: ${response.status} - ${errorText}`)
    }

    // 获取 Answer SDP
    const answerSdp = await response.text()
    console.log('Cloudflare WebRTC: received answer')

    await cfPeerConnection.setRemoteDescription({
      type: 'answer',
      sdp: answerSdp
    })

    // 绑定视频事件
    bindVideoEvents()
  } catch (error) {
    console.error('Cloudflare WebRTC 连接失败:', error)
    cfWebrtcStatus.value = 'failed'
    emit('error', { type: 'cloudflare-webrtc', message: String(error) })
  }
}

function destroyCloudflareWebRTC() {
  if (cfPeerConnection) {
    cfPeerConnection.close()
    cfPeerConnection = null
  }
  cfWebrtcStatus.value = 'idle'
  if (videoRef.value) {
    videoRef.value.srcObject = null
  }
}

// 初始化 WebRTC (go2rtc)
async function initWebRTC() {
  if (!videoRef.value || !props.go2rtcUrl || !props.streamName) return

  webrtcStatus.value = 'connecting'

  try {
    // 创建 RTCPeerConnection
    peerConnection = new RTCPeerConnection({
      iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
    })

    // 监听远程流
    peerConnection.ontrack = (event) => {
      if (videoRef.value && event.streams[0]) {
        videoRef.value.srcObject = event.streams[0]
        webrtcStatus.value = 'connected'
        if (props.autoplay) {
          videoRef.value.play()
        }
      }
    }

    // 监听连接状态
    peerConnection.oniceconnectionstatechange = () => {
      if (!peerConnection) return
      const state = peerConnection.iceConnectionState
      if (state === 'connected' || state === 'completed') {
        webrtcStatus.value = 'connected'
      } else if (state === 'failed' || state === 'disconnected') {
        webrtcStatus.value = 'failed'
        emit('error', { type: 'webrtc', message: `ICE connection ${state}` })
      }
    }

    // 添加音视频收发器
    peerConnection.addTransceiver('video', { direction: 'recvonly' })
    peerConnection.addTransceiver('audio', { direction: 'recvonly' })

    // 创建 Offer
    const offer = await peerConnection.createOffer()
    await peerConnection.setLocalDescription(offer)

    // 发送 Offer 到 go2rtc 并获取 Answer
    const apiUrl = `${props.go2rtcUrl}/api/webrtc?src=${encodeURIComponent(props.streamName)}`
    const response = await fetch(apiUrl, {
      method: 'POST',
      headers: { 'Content-Type': 'application/sdp' },
      body: offer.sdp
    })

    if (!response.ok) {
      throw new Error(`go2rtc API 请求失败: ${response.status}`)
    }

    const answerSdp = await response.text()
    await peerConnection.setRemoteDescription({
      type: 'answer',
      sdp: answerSdp
    })

    // 绑定视频事件
    bindVideoEvents()
  } catch (error) {
    console.error('WebRTC 连接失败:', error)
    webrtcStatus.value = 'failed'
    emit('error', { type: 'webrtc', message: String(error) })
  }
}

function destroyWebRTC() {
  if (peerConnection) {
    peerConnection.close()
    peerConnection = null
  }
  webrtcStatus.value = 'idle'
  if (videoRef.value) {
    videoRef.value.srcObject = null
  }
}

// 公开方法
function play() {
  if (videoRef.value) {
    videoRef.value.play()
  }
}

function pause() {
  if (videoRef.value) {
    videoRef.value.pause()
  }
}

function stop() {
  if (videoRef.value) {
    videoRef.value.pause()
    videoRef.value.currentTime = 0
  }
}

function setVolume(volume: number) {
  if (videoRef.value) {
    videoRef.value.volume = volume
  }
}

function setMuted(muted: boolean) {
  if (videoRef.value) {
    videoRef.value.muted = muted
  }
}

function screenshot() {
  if (videoRef.value) {
    const canvas = document.createElement('canvas')
    canvas.width = videoRef.value.videoWidth
    canvas.height = videoRef.value.videoHeight
    const ctx = canvas.getContext('2d')
    ctx?.drawImage(videoRef.value, 0, 0)
    const link = document.createElement('a')
    link.download = `screenshot-${Date.now()}.png`
    link.href = canvas.toDataURL('image/png')
    link.click()
  }
}

function fullscreen() {
  if (wrapperRef.value) {
    wrapperRef.value.requestFullscreen?.()
  }
}

// WebRTC 重连
function reconnect() {
  if (props.playerType === 'webrtc') {
    destroyWebRTC()
    initWebRTC()
  } else if (props.playerType === 'cloudflare-webrtc') {
    destroyCloudflareWebRTC()
    initCloudflareWebRTC()
  }
}

defineExpose({
  play,
  pause,
  stop,
  setVolume,
  setMuted,
  screenshot,
  fullscreen,
  reconnect,
  webrtcStatus,
  cfWebrtcStatus
})

watch(
  () => props.src,
  (newSrc) => {
    if (props.playerType === 'hls' && newSrc) {
      destroyHls()
      initHls()
    }
  }
)

// WebRTC 配置变化时重新连接
watch([() => props.go2rtcUrl, () => props.streamName], ([newUrl, newStream]) => {
  if (props.playerType === 'webrtc' && newUrl && newStream) {
    destroyWebRTC()
    initWebRTC()
  }
})

// Cloudflare WebRTC 配置变化时重新连接
watch(
  () => props.videoId,
  (newVideoId) => {
    if (props.playerType === 'cloudflare-webrtc' && newVideoId) {
      destroyCloudflareWebRTC()
      initCloudflareWebRTC()
    }
  }
)

onMounted(() => {
  if (props.playerType === 'hls') {
    initHls()
  } else if (props.playerType === 'webrtc') {
    initWebRTC()
  } else if (props.playerType === 'cloudflare-webrtc') {
    initCloudflareWebRTC()
  } else if (props.playerType === 'native') {
    bindVideoEvents()
  }
})

onBeforeUnmount(() => {
  destroyHls()
  destroyWebRTC()
  destroyCloudflareWebRTC()
})
</script>

<style lang="scss" scoped>
.video-player-wrapper {
  position: relative;
  width: 100%;
  height: 100%;
  background-color: #000;
  overflow: hidden;
}

.cloudflare-iframe,
.video-element,
.cloudflare-container {
  width: 100%;
  height: 100%;
  border: none;
}

.video-element {
  object-fit: contain;
}

// WebRTC 连接状态
.webrtc-status {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 12px 24px;
  border-radius: var(--radius-base);
  background-color: rgba(0, 0, 0, 0.7);
  color: #fff;
  font-size: 14px;

  .status-connecting {
    color: #409eff;
  }

  .status-failed {
    color: #f56c6c;
  }

  .status-idle {
    color: #909399;
  }
}
</style>
