<template>
  <div style="height: 100%">
    <el-card
      id="devicePosition"
      shadow="never"
      style="height: calc(100%); border: 0"
      :body-style="{ padding: '0px' }"
      class="border-none"
    >
      <el-container style="height: 100%">
        <!-- 左侧设备列表 -->
        <el-aside width="250px" style="background-color: #ffffff" :class="{ hidden: isFullscreen }">
          <DeviceTree :click-event="clickEvent" />
        </el-aside>

        <!-- 主体内容 -->
        <div style="padding: 0" class="el-main">
          <!-- 上方分屏按钮 -->
          <div
            height="5vh"
            style="text-align: left; font-size: 17px; line-height: 5vh; margin-bottom: 10px"
            :class="{ hidden: isFullscreen }"
          >
            {{ t('sip.splitview998531-1') }}
            <el-button
              type="success"
              style="margin-left: 10px"
              :class="{ active: spilt == 1 }"
              @click="spilt = 1"
              :icon="FullScreen"
              plain
              size="small"
            >
              {{ t('sip.splitview998531-2') }}
            </el-button>
            <el-button
              type="info"
              style="margin-left: 10px"
              :class="{ active: spilt == 4 }"
              @click="spilt = 4"
              :icon="Menu"
              plain
              size="small"
            >
              {{ t('sip.splitview998531-3') }}
            </el-button>
            <el-button
              type="warning"
              style="margin-left: 10px"
              :class="{ active: spilt == 9 }"
              @click="spilt = 9"
              :icon="Grid"
              plain
              size="small"
            >
              {{ t('sip.splitview998531-4') }}
            </el-button>

            <el-button @click="toggleFullscreen" :type="isFullscreen ? 'danger' : 'primary'">
              {{ isFullscreen ? '退出全屏' : '全屏' }}
            </el-button>
          </div>

          <!-- 分屏播放区域 -->
          <div
            style="height: 85vh; display: flex; flex-wrap: wrap"
            :class="{ 'fullscreen-layout': isFullscreen }"
          >
            <div
              v-for="i in spilt"
              :key="i"
              class="play-box"
              :style="liveStyle"
              :class="{ redborder: playerIdx == i - 1 }"
              @click="playerIdx = i - 1"
            >
              <div
                v-if="!videoUrl[i - 1] || i - 1 >= availableChannels.length"
                style="color: #ffffff; font-size: 30px; font-weight: bold"
              >
                {{ i }}
              </div>
              <player
                v-if="videoUrl[i - 1]"
                :ref="(el) => setPlayerRef(el, i - 1)"
                :videourl="videoUrl[i - 1]"
                :uid="playerUids[i - 1]"
                :playerInfo="
                  playerInfo.filter(
                    (item) =>
                      videoUrl[i - 1]?.includes(item.id) && videoUrl[i - 1]?.includes(item.deviceId)
                  )[0] || undefined
                "
                fluent
                autoplay
                @screenshot="shot"
                class="player-wrap"
                @destroy="destroy"
              />
            </div>
          </div>
        </div>
      </el-container>
    </el-card>
  </div>
</template>

<script setup>
import { ref, reactive, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
import { useRoute } from 'vue-router'
import { FullScreen, Menu, Grid } from '@element-plus/icons-vue'
// import player from './components/player/jessibuca.vue'
import player from './components/player/easy.vue'
import DeviceTree from './components/player/DeviceTree.vue'
import { startPlay } from '@/api/pms/video/channel'
import { listSipDeviceChannel } from '@/api/pms/video/sipdevice'

const { t } = useI18n()

// 使用组合式API
const route = useRoute()

// refs
const playerRefs = ref([])

// 为每个播放器生成稳定的 UID
const playerUids = ref([])

// 数据状态
const videoUrl = ref([''])
const spilt = ref(1) //分屏
const playerIdx = ref(0) //激活播放器
const updateLooper = ref(0) //数据刷新轮训标志
const count = ref(15)
const total = ref(0)
const loading = ref(false)

// 新增：存储可用通道
const availableChannels = ref([])

// 设置播放器引用
const setPlayerRef = (el, index) => {
  if (el) {
    playerRefs.value[index] = el
  }
}

// 计算属性 - 直播样式
const liveStyle = computed(() => {
  let style = {}
  // switch (spilt.value) {
  //   case 4:
  //     style = { width: '40%', height: '49%' }
  //     break
  //   case 9:
  //     style = { width: '27%', height: '32%' }
  //     break
  // }

  if (spilt.value === 1) {
    if (isFullscreen.value) {
      style = { width: '100%', height: '100%' }
    } else {
      style = { width: '81%', height: '99%', 'margin-right': '5px' }
    }
  }

  if (spilt.value === 4) {
    if (isFullscreen.value) {
      style = { width: '50%', height: '50%' }
    } else {
      style = { width: '40%', height: '49%', 'margin-right': '5px' }
    }
  }

  if (spilt.value === 9) {
    if (isFullscreen.value) {
      style = { width: '33.3%', height: '33.3%' }
    } else {
      style = { width: '27%', height: '32%', 'margin-right': '5px' }
    }
  }

  nextTick(() => {
    for (let i = 0; i < Math.min(spilt.value, availableChannels.value.length || spilt.value); i++) {
      const player = playerRefs.value[i]
      if (player && typeof player.updatePlayerDomSize === 'function') {
        player.updatePlayerDomSize()
      }
    }
  })

  return style
})

const loadAdditionalChannelsForSplit = async (newSplit, oldSplit) => {
  loading.value = true
  try {
    const currentlyLoaded = Math.min(oldSplit, availableChannels.value.length)
    const toBeLoaded = Math.min(newSplit, availableChannels.value.length)

    // 使用数组存储所有要执行的异步操作
    const operations = []

    for (let i = currentlyLoaded; i < toBeLoaded; i++) {
      const channelData = availableChannels.value[i]

      if (channelData._playUrl) {
        // 同步操作：立即设置URL
        setPlayUrl(channelData._playUrl, i)
      } else {
        // 异步操作：稍后并行执行
        operations.push({
          index: i,
          channelData,
          playData: {
            deviceSipId: channelData.deviceId,
            channelSipId: channelData.basicData?.channelSipId || channelData.id,
            name: channelData.name || `通道${i + 1}`,
            ...channelData.basicData
          }
        })
      }
    }

    // 并行执行所有sendDevicePush请求
    if (operations.length > 0) {
      const promises = operations.map(({ playData, index, channelData }) =>
        sendDevicePush(playData, index)
          .then(() => {
            // 成功后的回调
            if (videoUrl.value[index]) {
              channelData._playUrl = videoUrl.value[index]
            }
            return { success: true, index }
          })
          .catch((error) => {
            console.error(`通道${index + 1}加载失败:`, error)
            return { success: false, index, error }
          })
      )

      // 使用allSettled而不是all，这样即使有失败也不会中断其他请求
      await Promise.allSettled(promises)
    }
  } catch (error) {
    console.error('加载新增通道出错:', error)
  } finally {
    loading.value = false
  }
}

// 方法2：并行销毁，提高效率
const destroyAllPlayersAsync = async () => {
  if (!playerRefs.value || playerRefs.value.length === 0) {
    console.log('没有播放器需要销毁')
    return true
  }

  console.log(`开始并行销毁 ${playerRefs.value.length} 个播放器`)

  try {
    // 收集所有销毁 Promise
    const destroyPromises = playerRefs.value
      .filter((player) => player && typeof player.destroy === 'function')
      .map((player, index) => {
        return Promise.resolve().then(async () => {
          try {
            await player.destroy()
            console.log(`播放器 ${index} 销毁完成`)
            return { success: true, index }
          } catch (error) {
            console.error(`播放器 ${index} 销毁失败:`, error)
            return { success: false, index, error }
          }
        })
      })

    // 并行执行所有销毁
    const results = await Promise.allSettled(destroyPromises)

    // 统计结果
    const successCount = results.filter((r) => r.status === 'fulfilled' && r.value.success).length
    const failedCount = results.length - successCount

    console.log(`销毁完成: 成功 ${successCount} 个, 失败 ${failedCount} 个`)

    // 清空引用数组
    playerRefs.value = []

    return failedCount === 0
  } catch (error) {
    console.error('并行销毁过程中出错:', error)
    return false
  }
}

// watch(
//   () => spilt.value,
//   async (newSplit, oldSplit) => {
//     playerUids.value = Array.from({ length: newSplit }, (_, i) => `player_${i}`)
//     // 先销毁所有现有播放器，确保资源释放
//     await destroyAllPlayersAsync()
//     // 如果当前有选中的设备
//     if (currentDevice.value && availableChannels.value.length > 0) {
//       await nextTick()

//       // 只加载新出现的播放器，不重新加载已有播放器
//       await loadAdditionalChannelsForSplit(newSplit, oldSplit)
//     }
//   },
//   { immediate: false }
// )

watch(
  () => spilt.value,
  async (newSplit, oldSplit) => {
    playerUids.value = Array.from({ length: newSplit }, (_, i) => `player_${i}`)

    // 直接重新加载所有视频
    if (currentDevice.value && availableChannels.value.length > 0) {
      await destroyAllPlayersAsync()
      await nextTick()

      // 重新分配所有通道
      await assignChannelsToPlayers(availableChannels.value)
    } else {
      // 清空所有位置
      videoUrl.value = Array(newSplit).fill('')
      playerRefs.value = []
    }
  },
  { immediate: false }
)

// 监听路由变化
watch(
  () => route.fullPath,
  () => {
    checkPlayByParam()
  }
)

// 全屏状态
const isFullscreen = ref(false)

// 切换全屏
const toggleFullscreen = () => {
  const container = document.getElementById('devicePosition') // 获取全屏容器
  if (!container) return

  if (!isFullscreen.value) {
    // 进入全屏
    if (container.requestFullscreen) {
      container.requestFullscreen()
    } else if (container.webkitRequestFullscreen) {
      container.webkitRequestFullscreen() // Safari
    } else if (container.mozRequestFullScreen) {
      container.mozRequestFullScreen() // Firefox
    } else if (container.msRequestFullscreen) {
      container.msRequestFullscreen() // IE/Edge
    }
  } else {
    // 退出全屏
    if (document.exitFullscreen) {
      document.exitFullscreen()
    } else if (document.webkitExitFullscreen) {
      document.webkitExitFullscreen() // Safari
    } else if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen() // Firefox
    } else if (document.msExitFullscreen) {
      document.msExitFullscreen() // IE/Edge
    }
  }
}

// 监听全屏状态变化
const handleFullscreenChange = () => {
  isFullscreen.value = !!(
    document.fullscreenElement ||
    document.webkitFullscreenElement ||
    document.mozFullScreenElement ||
    document.msFullscreenElement
  )

  // 动态调整主内容区域宽度
  const mainContent = document.querySelector('.el-main')
  if (mainContent) {
    if (isFullscreen.value) {
      mainContent.style.width = '100vw'
      mainContent.style.marginLeft = '0'
    } else {
      mainContent.style.width = ''
      mainContent.style.marginLeft = ''
    }
  }
}

// 生命周期钩子
onMounted(() => {
  checkPlayByParam()
  playerUids.value = Array.from({ length: spilt.value }, (_, i) => `player_${i}`)
  document.addEventListener('fullscreenchange', handleFullscreenChange)
  document.addEventListener('webkitfullscreenchange', handleFullscreenChange)
  document.addEventListener('mozfullscreenchange', handleFullscreenChange)
  document.addEventListener('MSFullscreenChange', handleFullscreenChange)
})

onUnmounted(() => {
  clearTimeout(updateLooper.value)
  document.removeEventListener('fullscreenchange', handleFullscreenChange)
  document.removeEventListener('webkitfullscreenchange', handleFullscreenChange)
  document.removeEventListener('mozfullscreenchange', handleFullscreenChange)
  document.removeEventListener('MSFullscreenChange', handleFullscreenChange)
})

// 销毁事件
const destroy = (idx) => {
  console.log(idx)
  clear(idx.substring(idx.length - 1))
}
const currentDevice = ref(null) // 存储当前选中的设备信息
// 点击事件
let playerInfo = ref([])

const clickEvent = async (data) => {
  // 情况1：点击的是设备节点 (type === 0)
  if (data.type === 0) {
    // 重置选中的空闲槽位
    selectedEmptySlot.value = -1

    currentDevice.value = {
      id: data.userData?.serialNumber,
      name: data.name,
      data: data
    }
    const deviceId = data.userData?.serialNumber
    if (!deviceId) return

    loading.value = true
    try {
      const channels = await getDeviceChannels(deviceId)
      const cameraChannels = channels.filter(
        (channel) => channel.basicData.model === 'Camera' && channel.basicData.status === 3
      )
      availableChannels.value = cameraChannels

      playerInfo.value = []
      cameraChannels.forEach((channel) => {
        playerInfo.value.push(channel)
      })

      if (!cameraChannels || cameraChannels.length === 0) {
        console.warn('该设备下没有可用的摄像头通道')
        const newVideoUrls = Array(spilt.value).fill('')
        videoUrl.value = newVideoUrls
        return
      }

      await assignChannelsToPlayers(cameraChannels)
    } catch (error) {
      console.error('处理设备通道时出错:', error)
    } finally {
      loading.value = false
    }
  }
  // 情况2：点击的是具体的通道节点
  else if (data.userData?.channelSipId) {
    console.log('点击了通道节点，数据:', data)
    if (data.online === false) {
      ElMessage.warning('通道未在线')
      return
    }
    // 检查是否有选中的空闲槽位
    let targetIndex = selectedEmptySlot.value !== -1 ? selectedEmptySlot.value : playerIdx.value

    // 验证目标索引是否在有效范围内
    if (targetIndex >= spilt.value) {
      targetIndex = playerIdx.value // 回退到当前选中的播放器
    }

    // 重置选中的空闲槽位
    selectedEmptySlot.value = -1

    await sendDevicePush(data.userData, targetIndex)
  }
}

const getDeviceChannels = async (deviceId) => {
  try {
    const response = await listSipDeviceChannel(deviceId)
    console.log('获取设备通道列表成功:', response)
    return response || []
  } catch (error) {
    console.error('获取设备通道列表失败:', error)
    return []
  }
}

const assignChannelsToPlayers = async (channels) => {
  const currentSplit = spilt.value
  const actualChannels = Math.min(channels.length, currentSplit)
  // 初始化所有播放器位置
  const newVideoUrls = Array(currentSplit).fill('')
  videoUrl.value = newVideoUrls

  // 为每个可用通道分配播放器
  for (let i = 0; i < actualChannels; i++) {
    await new Promise((resolve) => setTimeout(resolve, 50))

    const channelData = channels[i]
    const playData = {
      deviceSipId: channelData.deviceId,
      channelSipId: channelData.basicData?.channelSipId || channelData.id,
      name: channelData.name || `通道${i + 1}`,
      ...channelData.basicData
    }

    await sendDevicePush(playData, i)
  }
}

// 通知设备上传媒体流
const sendDevicePush = async (itemData, targetIndex = null) => {
  // 关键修改：允许从外部传入 targetIndex，默认使用当前激活的 playerIdx
  const playIndex = targetIndex !== null ? targetIndex : playerIdx.value

  // 确保索引在有效范围内
  const validIndex = Math.min(playIndex, spilt.value - 1)

  save(itemData, validIndex) // 保存数据也要使用正确的索引

  let deviceId = itemData.deviceSipId
  let channelId = itemData.channelSipId
  loading.value = true

  return startPlay(deviceId, channelId)
    .then((response) => {
      let res = response
      if (window.location.protocol === 'http:') {
        itemData.playUrl = res.playurl
      } else {
        itemData.playUrl = res.playurl
      }
      itemData.streamId = res.streamId
      setPlayUrl(itemData.playUrl, validIndex) // 播放URL设置到指定位置
    })
    .finally(() => {
      loading.value = false
    })
}

let playInfoRes = ref('')
// 设置播放URL
const setPlayUrl = (url, idx) => {
  console.log('设置播放URL:', url, '索引:', idx)
  // 确保数组长度足够
  while (videoUrl.value.length <= idx) {
    videoUrl.value.push('')
  }

  const newVideoUrls = [...videoUrl.value]
  newVideoUrls[idx] = url
  videoUrl.value = newVideoUrls

  setTimeout(() => {
    window.localStorage.setItem('videoUrl', JSON.stringify(videoUrl.value))
  }, 100)
}

// 检查播放参数
const checkPlayByParam = () => {
  let { deviceId, channelId } = route.query
  if (deviceId && channelId) {
    sendDevicePush({ deviceId, channelId })
  }
}

// 存储当前选中的空闲槽位
const selectedEmptySlot = ref(-1)

const handleEmpty = (i) => {
  // 计算当前点击的空闲槽位的实际索引
  const slotIndex = availableChannels.value.length + i - 1
  selectedEmptySlot.value = slotIndex
  playerIdx.value = slotIndex

  console.log('选中空闲槽位:', slotIndex)
}

// 截图处理
const shot = (e) => {
  var base64ToBlob = function (code) {
    let parts = code.split(';base64,')
    let contentType = parts[0].split(':')[1]
    let raw = window.atob(parts[1])
    let rawLength = raw.length
    let uInt8Array = new Uint8Array(rawLength)
    for (let i = 0; i < rawLength; ++i) {
      uInt8Array[i] = raw.charCodeAt(i)
    }
    return new Blob([uInt8Array], {
      type: contentType
    })
  }

  let aLink = document.createElement('a')
  let blob = base64ToBlob(e)
  let evt = document.createEvent('HTMLEvents')
  evt.initEvent('click', true, true)
  aLink.download = 't("sip.splitview998531-5")'
  aLink.href = URL.createObjectURL(blob)
  aLink.click()
}

// 保存数据
const save = (item, index) => {
  let dataStr = window.localStorage.getItem('playData') || '[]'
  let data = JSON.parse(dataStr)
  // 确保数组长度足够
  while (data.length <= index) {
    data.push(null)
  }
  data[index] = item
  window.localStorage.setItem('playData', JSON.stringify(data))
}

// 清除数据
const clear = (idx) => {
  let dataStr = window.localStorage.getItem('playData') || '[]'
  let data = JSON.parse(dataStr)
  if (data.length > idx - 1) {
    data[idx - 1] = null
  }
  console.log(data)
  window.localStorage.setItem('playData', JSON.stringify(data))
}
</script>

<style scoped>
.btn {
  margin: 0 10px;
}

.btn:hover {
  color: #409eff;
}

.btn.active {
  color: #409eff;
}

.redborder {
  border: 2px solid red !important;
}

.play-box {
  background-color: #000000;
  border: 1px solid #505050;
  display: flex;
  align-items: center;
  justify-content: center;
  /* margin-right: 10px; */
  position: relative;
  /* border-radius: 5px; */
}

.empty-box {
  background-color: #333;
  opacity: 0.5;
  cursor: default;
}

.player-wrap {
  position: absolute;
  top: 0px;
  height: 100% !important;
}

.hidden {
  display: none !important;
}

/* 全屏时隐藏滚动条 */
:-webkit-full-screen {
  overflow: hidden;
}

:-moz-full-screen {
  overflow: hidden;
}

:-ms-fullscreen {
  overflow: hidden;
}

/* :fullscreen {
  height: 100vh !important;
  width: 100vw !important;
  margin: 0 !important;

  position: fixed !important;
  top: 0 !important;
  left: 0 !important;
  overflow: hidden !important;
  max-width: 100vw !important;
  max-height: 100vh !important;
} */

.fullscreen-layout {
  height: 100vh !important;
  width: 100vw !important;
  margin: 0 !important;
  padding: 0 !important;
  position: fixed !important;
  top: 0 !important;
  left: 0 !important;
  right: 0 !important;
  overflow: hidden !important;
  max-width: 100vw !important;
  max-height: 100vh !important;
}
</style>
