<template>
  <div
    class="live-video-box"
    :class="{ 'no-title': !showTitle }"
    :style="{ height }"
  >
    <!-- 有视频时显示播放器 -->
    <div v-if="videoUrl" class="video-container">
      <!-- 视频标题和关闭按钮 -->
      <div v-if="showTitle" class="live-video-title">
        {{ videoData?.flnm }}
        <div class="title-actions">
          <CloseOutlined @click="handleClose" />
        </div>
      </div>
      <div :id="playerId" class="video-player"></div>
      <!-- 自定义错误提示 -->
      <div v-if="showError" class="custom-error-overlay">
        <div class="error-content">
          <i class="iconfont icon-jiankong error-icon"></i>
          <div class="error-text">数据源错误，无法加载视频</div>
        </div>
      </div>
    </div>

    <!-- 无视频时显示占位 -->
    <div v-else class="video-empty">
      <i class="iconfont icon-jiankong"></i>
      <div>请选择视频</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, computed } from 'vue';
import { CloseOutlined } from '@ant-design/icons-vue';
import videojs from 'video.js';
import 'video.js/dist/video-js.css';
const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;

// 错误提示显示状态
const showError = ref(false);

// 注册 HLS 支持（video.js 8.x 内置了 HLS 支持）

interface VideoData {
  flnm?: string;
  stnm?: string;
  url?: string;
  urls?: string[];
  [key: string]: any;
}

const props = withDefaults(
  defineProps<{
    videoData?: VideoData | null;
    height?: string;
    monitorType?: 'live' | 'record'; // 监控类型：live-实时视频, record-录像
    showTitle?: boolean; // 是否显示标题栏
  }>(),
  {
    showTitle: true
  }
);

const emit = defineEmits<{
  close: [nodeKey?: string];
}>();

// 生成唯一ID
const playerId = `video-player-${Math.random().toString(36).substr(2, 9)}`;
let player: any = null;

// 获取第一个有效的URL
const videoUrl = computed(() => {
  if (!props.videoData) return '';

  // 优先使用url字段
  if (props.videoData.url) return props.videoData.url;

  // 其次使用urls数组的第一个
  if (
    props.videoData.urls &&
    Array.isArray(props.videoData.urls) &&
    props.videoData.urls.length > 0
  ) {
    return props.videoData.urls[0];
  }

  return '';
});

// 初始化 video.js 播放器
const initPlayer = () => {
  if (!videoUrl.value) return;

  // 销毁旧播放器
  if (player) {
    player.dispose();
    player = null;
  }

  // 重试计数器（用于限制重试次数）
  let retryCount = 0;
  const maxRetries = 5;

  try {
    // 创建 video 元素
    const videoElement = document.createElement('video');
    videoElement.className = 'video-js vjs-default-skin vjs-big-play-centered';
    videoElement.setAttribute('id', playerId);
    videoElement.setAttribute('playsinline', 'playsinline');
    videoElement.setAttribute('webkit-playsinline', 'webkit-playsinline');

    // 将 video 元素添加到容器
    const container = document.getElementById(playerId);
    if (container) {
      container.innerHTML = '';
      container.appendChild(videoElement);
    }

    // 根据 monitorType 判断是否为直播流
    // live: 实时视频流（m3u8），显示直播UI
    // record: 录像文件，显示进度条
    const isLiveStream = props.monitorType === 'live';

    // 根据 URL 后缀或监控类型确定视频 MIME Type
    const getVideoType = (url: string): string => {
      const lowerUrl = url.toLowerCase();

      // 优先根据 URL 后缀判断
      if (lowerUrl.includes('.m3u8')) {
        return 'application/x-mpegURL'; // HLS 流
      } else if (lowerUrl.includes('.mp4')) {
        return 'video/mp4';
      } else if (lowerUrl.includes('.webm')) {
        return 'video/webm';
      } else if (lowerUrl.includes('.ogg') || lowerUrl.includes('.ogv')) {
        return 'video/ogg';
      } else if (lowerUrl.includes('.avi')) {
        return 'video/x-msvideo';
      } else if (lowerUrl.includes('.mov')) {
        return 'video/quicktime';
      } else if (lowerUrl.includes('.wmv')) {
        return 'video/x-ms-wmv';
      } else if (lowerUrl.includes('.flv')) {
        return 'video/x-flv';
      }

      // 如果 URL 中没有明确后缀，根据监控类型判断
      return isLiveStream ? 'application/x-mpegURL' : 'video/mp4';
    };

    const videoType = getVideoType(videoUrl.value);

    // 初始化 video.js
    player = videojs(videoElement, {
      autoplay: true,
      muted: true,
      controls: true,
      fluid: false,
      width: '100%',
      height: '100%',
      preload: 'auto',
      playbackRates: [0.5, 1, 1.5, 2],
      liveui: isLiveStream, // 直播流显示直播UI
      // 录像模式下禁用直播相关功能
      inactivityTimeout: 0, // 禁用不活动超时
      controlBar: {
        children: [
          'playToggle',
          'volumePanel',
          'currentTimeDisplay',
          'timeDivider',
          'durationDisplay',
          'progressControl',
          'liveDisplay',
          'remainingTimeDisplay',
          'customControlSpacer',
          'playbackRateMenuButton',
          'fullscreenToggle'
        ]
      },
      html5: {
        hls: {
          enableLowInitialPlaylist: true,
          smoothQualityChange: true
        }
      },
      sources: [
        {
          src: videoUrl.value,
          type: videoType // 指定视频类型
        }
      ]
    });

    // 如果是录像模式，隐藏直播指示器
    if (!isLiveStream) {
      player.ready(() => {
        const liveDisplay = player.controlBar.getChild('liveDisplay');
        if (liveDisplay) {
          liveDisplay.el().style.display = 'none';
        }
      });
    }

    // 监听错误事件
    player.on('error', () => {
      const error = player.error();
      console.error('播放器错误:', error);

      // 检查是否已达到最大重试次数
      if (retryCount >= maxRetries) {
        console.warn(`已达到最大重试次数(${maxRetries}次)，停止重试`);
        // 显示自定义错误提示层
        showError.value = true;
        return;
      }

      // 增加重试计数
      retryCount++;
      console.log(`视频加载失败，正在进行第 ${retryCount}/${maxRetries} 次重试...`);

      // 立即显示自定义错误提示层
      showError.value = true;

      // 延迟后重试
      setTimeout(() => {
        try {
          if (player && videoUrl.value) {
            // 隐藏错误提示层（重试时）
            showError.value = false;
            player.src({
              src: videoUrl.value,
              type: videoType
            });
            player.load();
            player.play();
          }
        } catch (e) {
          console.error('重试加载视频失败:', e);
          // 如果重试失败且未达到最大次数，继续重试
          if (retryCount < maxRetries) {
            setTimeout(() => {
              if (player) {
                player.error(); // 触发下一次错误处理
              }
            }, 100);
          }
        }
      }, 3000);
    });

    // 监听加载完成
    player.on('loadeddata', () => {
      // 加载成功时重置重试计数器
      retryCount = 0;
      // 隐藏错误提示
      showError.value = false;
    });

    // 监听播放状态
    player.on('play', () => {});

    // 监听暂停
    player.on('pause', () => {});

    // 监听等待（缓冲）
    player.on('waiting', () => {});
  } catch (error) {
    // 静默处理错误
  }
};

// 关闭视频
const handleClose = () => {
  // 传递节点的 key 给父组件
  emit('close', props.videoData?.key);
};

// 监听视频URL变化
watch(
  videoUrl,
  (newUrl, oldUrl) => {
    if (newUrl && newUrl !== oldUrl) {
      // URL 变化时延迟初始化，确保 DOM 已更新
      setTimeout(() => initPlayer(), 200);
    } else if (newUrl && !oldUrl) {
      // 首次加载
      setTimeout(() => initPlayer(), 100);
    }
  },
  { immediate: true }
);

onMounted(() => {
  if (videoUrl.value) {
    initPlayer();
  }
});

onUnmounted(() => {
  // 清理播放器
  if (player) {
    player.dispose();
    player = null;
  }
});
</script>

<style scoped lang="scss">
.live-video-box {
  width: 100%;
  height: 100%;
  position: relative;
  background-color: #000;
  border-radius: 4px;
  overflow: hidden;
  .live-video-title {
    width: 100%;
    height: 40px;
    background-color: #2f6b98;
    display: flex;
    padding: 8px 16px;
    color: #fff;
    font-size: 13px;
    justify-content: space-between;
    align-items: center;

    .title-actions {
      display: flex;
      gap: 8px;
      align-items: center;

      span {
        font-size: 16px;
        cursor: pointer;
        transition: opacity 0.2s;

        &:hover {
          opacity: 0.8;
        }
      }
    }
  }

  .video-container {
    width: 100%;
    height: calc(100% - 40px);
    position: relative;

    .video-player {
      width: 100%;
      height: 100%;

      // video.js 样式优化
      :deep(.video-js) {
        width: 100%;
        height: 100%;
        background-color: #000;

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

  &.no-title {
    .video-container {
      height: 100%;
    }
  }

  .custom-error-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10;

    .error-content {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;

      .error-icon {
        font-size: 48px;
        margin-bottom: 12px;
        opacity: 0.5;
        color: #999;
      }

      .error-text {
        font-size: 14px;
        color: #fff;
        text-align: center;
        margin-top: 12px;
      }
    }
  }

  .video-empty {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: #666;
    background-color: #1a1a1a;

    i {
      font-size: 48px;
      margin-bottom: 12px;
      opacity: 0.5;
    }

    div {
      font-size: 13px;
      color: #999;
    }
  }
}
</style>
