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

import { useRouter } from 'vue-router'
import { runApi, runApiAudio } from '~/composables/api'

interface Sentence {
  begin_time: number
  duration: number
  end_time: number
  speaker: string
  text: string
}

interface AudioResult {
  sentences: Sentence[]
  total_sentences: number
}

const 隐患等级字典: Record<number, string> = {
  0: '一般隐患',
  1: '重大隐患',
}

const 置信度字典: Record<number, string> = {
  0: '疑似',
  1: '确信',
}

interface HazardItem {
  隐患编号: string
  物体编号: string
  物体类型: string
  隐患名称: string
  隐患等级: string
  置信度: string
  时间点: string
  跳转时间点: number
  隐患描述: string
  依据: string
  整改建议: string
}

interface DataFormat {
  隐患列表: [number, string][]
  对话列表: [number, string, string, string][]
  隐患范围字典: Record<string, { ranges: number[], level: number, tip: string }>
  隐患数据: HazardItem[]
}

interface ResultObject {
  tag_id: number // 隐患类型id
  base_id: number // 依据id
  track_id: string // 物体追踪id
  hazard_track_id: number // 隐患追踪id
  class_id: number // 物体类型id
  conf: number // 置信度 0: 疑似 1: 确信
  level: number // 隐患等级 0: 一般隐患 1: 重大隐患
  start_frame: number // 开始帧
  end_frame: number // 结束帧
  start_sec: number // 开始时间点
  location: string // 位置
  recommend: string // 整改建议
}

interface ResultData {
  class_list: string[]
  tag: string[]
  base: string[]
  objects: ResultObject[]
}
// =============== 2. 响应式数据 ===============

const router = useRouter()

const vidUrl = ref('')
const resultData = ref<ResultData>({
  class_list: [],
  tag: [],
  base: [],
  objects: [],
})

const videoRef = ref<HTMLVideoElement>()
const data = ref<DataFormat>({
  隐患列表: [],
  隐患范围字典: {},
  隐患数据: [],
  对话列表: [],
})
// const data = ref({
//   隐患列表: ['隐患1', '隐患2'],
//   物体列表: ['物体1', '物体2', '物体3', '物体4', '物体5'],
//   隐患数据: [
//     {
//       隐患名称: '隐患1',
//       时间点: '00:00:00',
//       跳转时间点: 0,
//       隐患描述: '隐患1的描述',
//       依据: '依据1',
//       整改建议: '整改建议1',
//     },
//     {
//       隐患名称: '隐患2',
//       时间点: '00:00:03',
//       跳转时间点: 3,
//       隐患描述: '隐患2的描述',
//       依据: '依据2',
//       整改建议: '整改建议2',
//     },
//   ],
// })

const selectedHazard = ref(-1)
const currentFrame = ref(0)
const videoDuration = ref(0)
const FPS = 30
const totalFrames = computed(() => {
  if (videoDuration.value > 0) {
    return Math.floor(videoDuration.value * FPS)
  }
  const objects = resultData.value.objects
  if (!objects || objects.length === 0)
    return 300
  const maxEndFrame = Math.max(...objects.map(obj => obj.end_frame || obj.start_frame))
  return maxEndFrame + 100
})

function handleTimelineHazardClick(hazardId: string) {
  selectedHazard.value = Number(hazardId)
  handleJumpToHazard(Number(hazardId))
}

function handleFrameChange(frame: number) {
  const videoEl = videoRef.value
  if (!videoEl)
    return
  const seconds = frame / FPS
  videoEl.currentTime = Math.min(seconds, videoEl.duration)
}

function updateCurrentFrame() {
  const videoEl = videoRef.value
  if (!videoEl)
    return
  currentFrame.value = Math.floor(videoEl.currentTime * 30)
}

function handleVideoLoadedMetadata() {
  const videoEl = videoRef.value
  if (!videoEl)
    return
  videoDuration.value = videoEl.duration
}

function getData() {
  const { class_list, tag, base, objects } = resultData.value

  // console.log('检查数据', resultData.value)

  data.value.隐患列表 = (objects || []).map((obj: any) => {
    return [
      obj.level,
      // resultData.value?.class_list?.[obj.class_id] || '',
      tag?.[obj.tag_id] || '',
    ]
  })

  data.value.隐患范围字典 = {}
  ;(objects || []).forEach((obj: any) => {
    const 编号 = String(obj.hazard_track_id)
    if (!data.value.隐患范围字典[编号]) {
      data.value.隐患范围字典[编号] = {
        ranges: [obj.start_frame, obj.end_frame],
        level: obj.level,
        tip: `${tag?.[obj.tag_id] || ''}`, // 隐患名称
        // tip: `(${resultData.value.class_list?.[obj.class_id] || ''}) ${tag?.[obj.tag_id] || ''}`,
      }
    }
  })

  // data.value.物体列表 = (objects || []).map((_: any, i: number) => `物体${i + 1}`)
  data.value.隐患数据 = (objects || []).map((obj: any) => {
    const jumpPoint = obj.start_sec || 0
    const hh = String(Math.floor(jumpPoint / 3600)).padStart(2, '0')
    const mm = String(Math.floor((jumpPoint % 3600) / 60)).padStart(2, '0')
    const ss = String(Math.floor(jumpPoint % 60)).padStart(2, '0')

    return {
      隐患编号: obj.hazard_track_id || '',
      物体编号: obj.track_id || '',
      物体类型: class_list?.[obj.class_id] || '',
      隐患名称: tag?.[obj.tag_id] || '',
      隐患等级: 隐患等级字典[obj.level],
      置信度: 置信度字典[obj.conf],
      时间点: `${hh}:${mm}:${ss}`,
      跳转时间点: jumpPoint,
      隐患描述: obj.location || '',
      依据: base?.[obj.base_id] || '',
      整改建议: obj.recommend || '',
    }
  })
}

// 点击隐患列表项，更新选中隐患
function handleHazardClick(item: string, index: number) {
  selectedHazard.value = index

  handleJumpToHazard(selectedHazard.value)
}

// 点击跳转到隐患时间点，更新视频播放
function handleJumpToHazard(index: number) {
  const seconds = data.value.隐患数据[index].跳转时间点
  // 实现跳转到指定时间点的逻辑
  // console.log(`跳转到时间点: ${seconds}`)

  handleJumpToTimePoint(seconds)
}

function handleJumpToTimePoint(seconds: number) {
  // 校验：必须是数字且大于等于0
  if (Number.isNaN(seconds) || seconds < 0)
    return

  const videoEl = videoRef.value
  if (!videoEl)
    return // 确保 DOM 已加载

  // 直接设置 currentTime 实现跳转
  videoEl.currentTime = seconds

  // 跳转后自动暂停
  videoEl.pause()
}

function getAudioRecData(res: any) {
  if (!res) {
    console.error('音频识别结果为空')
    return
  }

  let sentences = res.sentences
  if (!sentences && res.data) {
    sentences = res.data.sentences
  }

  if (!sentences) {
    console.error('未找到 sentences 字段，完整响应：', res)
    return
  }

  const conversationList: [number, string, string, string][] = []

  sentences.forEach((sentence: Sentence) => {
    const mins = Math.floor(sentence.begin_time / 60)
    const secs = Math.floor(sentence.begin_time % 60)
    const timeStr = `${mins}:${secs.toString().padStart(2, '0')}`

    conversationList.push([
      sentence.begin_time,
      timeStr,
      sentence.speaker,
      sentence.text,
    ])
  })

  data.value.对话列表 = conversationList
}

// 隐患列表项字段配置
// label: 显示名称
// key: 数据字段名
// group: 所属分组(行)
// transform: 数据转换函数
const hazardFields = [
  { label: '隐患编号', key: '隐患编号', group: 1, transform: (val: any) => val !== undefined ? val + 1 : '无' },
  { label: '物体编号', key: '物体编号', group: 1 },
  { label: '物体类型', key: '物体类型', group: 1 },
  { label: '隐患等级', key: '隐患等级', group: 2 },
  { label: '置信度', key: '置信度', group: 2 },
  { label: '时间点', key: '时间点', group: 2 },
  { label: '隐患名称', key: '隐患名称', group: 3 },
  { label: '隐患描述', key: '隐患描述', group: 4 },
  { label: '依据', key: '依据', group: 5 },
  { label: '整改建议', key: '整改建议', group: 6 },
]

const groupedFields = computed(() => {
  const groups: Record<number, typeof hazardFields> = {}
  hazardFields.forEach((field) => {
    const group = field.group || 0
    if (!groups[group])
      groups[group] = []
    groups[group].push(field)
  })
  return Object.values(groups).filter(g => g.length > 0)
})

function getFieldValue(field: typeof hazardFields[0]) {
  const value = data.value.隐患数据[selectedHazard.value]?.[field.key as keyof HazardItem]
  return field.transform ? field.transform(value) : (value || '无')
}

onMounted(() => {
  // 从路由参数中获取数据
  const vidFile = router.currentRoute.value.query.vid_file as string
  if (vidFile) {
    // 调用接口获取完整视频路径
    runApi('/get_full_vid_path', {
      vid_file: vidFile,
    }).then((res) => {
      // console.log('接口调用成功，返回数据：', res)
      vidUrl.value = (res as string[])[0]

      // 截取文件名
      const fileName = vidUrl.value.split('\\').pop() || ''
      // 去掉文件扩展名
      const fileNameNoExt = fileName.split('.')[0]
      // 文件扩展名
      // const fileExt = fileName.split('.')[1]
      // 临时拼接视频路径
      vidUrl.value = `http://localhost:8086/${fileNameNoExt}_h264.mp4`
    })

    // 临时拼接视频路径
    // 去掉文件扩展名
    // const fileNameNoExt = vidFile.split('.')[0]
    // // 文件扩展名
    // const fileExt = vidFile.split('.')[1]
    // vidUrl.value = `http://localhost:8086/${fileNameNoExt}_h264.${fileExt}`

    // 调用接口获取隐患数据
    runApi('/run', {
      vid_file: vidFile,
      run_sam3: false,
      run_inspection: false,
      gen_report: false,
    }).then((res) => {
      // console.log('接口调用成功，返回数据：', res[3])
      resultData.value = (res as any[])[3] as ResultData

      getData()

      if (data.value.隐患列表.length > 0) {
        selectedHazard.value = 0
        handleJumpToHazard(0)
      }
    })

    runApiAudio('result', 'GET', {
      path: vidFile,
      // path: 'VID_20251104_085655_024.AVI',
    }).then((res) => {
      getAudioRecData(res as AudioResult)
    })
  }
})
</script>

<template>
  <!-- 最外层容器：占满整个视口 -->
  <el-container style="margin: 0; height: 100%; flex-direction: column;">
    <el-header style="height: 30px; display: flex; align-items: center; border-bottom: 1px solid var(--ep-border-color);">
      <el-breadcrumb separator="/">
        <el-breadcrumb-item :to="{ path: '/' }">
          主页
        </el-breadcrumb-item>
        <el-breadcrumb-item>隐患检查结果</el-breadcrumb-item>
      </el-breadcrumb>
    </el-header>

    <!-- 内层容器：自动填充剩余高度 -->
    <el-container style="flex: 1; min-height: 0;">
      <el-aside width="200px" style="border-right: 1px solid var(--ep-border-color);">
        <!-- <el-row class="flex flex-col" style="border-bottom: 1px solid var(--ep-border-color);"> -->
        <el-row class="flex flex-col">
          <ItemList title="隐患" :data="data.隐患列表" @click="handleHazardClick" />
        </el-row>
        <!-- <el-row style="flex: 1; overflow-y: auto;">
          <ItemList title="物体列表" :data="data.物体列表" />
        </el-row> -->
      </el-aside>
      <el-container style="border-right: 1px solid var(--ep-border-color)">
        <el-main style="border-bottom: 1px solid var(--ep-border-color); padding: 0;">
          <div class="vid_box">
            <video
              ref="videoRef"
              :src="vidUrl"
              controls
              class="video"
              @timeupdate="updateCurrentFrame"
              @loadedmetadata="handleVideoLoadedMetadata"
            />
          </div>
        </el-main>
        <el-footer style="height: 200px; padding: 0px;">
          <Timeline
            style="height: 100%;"
            :current-frame="currentFrame"
            :total-frames="totalFrames"
            :hazard-ranges="data.隐患范围字典 as Record<string, { ranges: number[]; level: number; tip: string }>"
            @hazard-click="(id: number) => handleTimelineHazardClick(String(id))"
            @frame-change="handleFrameChange"
          />
        </el-footer>
      </el-container>
      <el-aside style="width: 300px;">
        <!-- <el-row style="border-bottom: 1px solid var(--ep-border-color);"> -->
        <el-row class="px-3 py-2">
          <el-col v-if="selectedHazard >= 0">
            <template v-for="group in groupedFields" :key="group[0].group">
              <el-row :gutter="12">
                <el-col v-for="field in group" :key="field.key" :span="24 / group.length">
                  <el-row class="result-title">
                    <el-text type="info" size="small">
                      {{ field.label }}
                    </el-text>
                  </el-row>
                  <el-row class="result-content">
                    <el-text v-if="field.key === '隐患等级' && getFieldValue(field) === '重大隐患'" type="danger">
                      {{ getFieldValue(field) }}
                    </el-text>
                    <el-text v-else-if="field.key === '置信度' && getFieldValue(field) === '疑似'" type="warning">
                      {{ getFieldValue(field) }}
                    </el-text>
                    <el-text v-else>
                      {{ getFieldValue(field) }}
                    </el-text>
                  </el-row>
                </el-col>
              </el-row>
              <div class="py-1" />
            </template>
            <el-row>
              <el-button style="width: 100%;" @click="handleJumpToHazard(selectedHazard)">
                跳转到隐患时间点
              </el-button>
            </el-row>
          </el-col>
          <el-col v-else>
            <el-row class="px-1 py-1">
              无选中隐患
            </el-row>
          </el-col>
        </el-row>
        <el-row v-if="data.对话列表.length > 0" style="flex: 1; overflow-y: auto; border-top: 1px solid var(--ep-border-color);">
          <SubtitleList title="对话" :data="data.对话列表" @click="(item: any[]) => handleJumpToTimePoint(Number(item[0]))" />
        </el-row>
        <!-- <el-row class="px-1 py-1">
          <el-button>
            查看报告
          </el-button>
        </el-row> -->
      </el-aside>
    </el-container>
  </el-container>
</template>

<style scoped lang="scss">
.vid_box {
  width: 100%;
  height: 100%;
  display: flex;
}
.vid_box video {
  width: 100%;
  height: 100%;
  object-fit: contain; /* 关键：保持比例 + 完整显示 + 自适应父盒子 */
}

.item-btn {
  width: 100%;
}

.result-title {
  padding: 0.25rem 0px;
}

.result-content {
  text-align: left;
  // line-height: 1.5rem;
}
</style>
