<script setup>
import LiveCover from './LiveCover.vue'
import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
import { useFileDialog } from '@vueuse/core'
import { useUserStore } from '@/stores/user'
import { upload } from '@/utils/upload'
import { useLive, readBlobAsBase64 } from '../composables/useLive'
import { useSocket } from '@/composables/useSocket'
import { saveTestRecord, getRecord } from '../api'
import { saveAs } from 'file-saver'
import md5 from 'blueimp-md5'
import dayjs from 'dayjs'
import { useLiveChat } from '../composables/useLiveChat'
import { useSpeechTranscriber } from '../composables/useSpeechTranscriber'

const props = defineProps({
  orderCount: { type: Number, default: 0 },
  isLocalUpload: { type: Boolean, default: false },
  onStart: { type: Function, default: () => {} },
  onStop: { type: Function, default: () => {} },
  onSentenceEnd: { type: Function, default: () => {} },
  onStatsChange: { type: Function, default: () => {} },
})

const { messages, viewers, stats, currentTime, start: startChat, stop: stopChat } = useLiveChat()
watch(
  () => [stats, viewers],
  () => {
    props.onStatsChange && props.onStatsChange({ ...stats, viewers: viewers.value.length })
  },
  { immediate: true, deep: true }
)

const detail = inject('detail')

const userName = computed(() => {
  const user = detail.value?.current_user || {}
  return user.real_name || user.nickname || user.username
})

const route = useRoute()

const userStore = useUserStore()
const ssoId = userStore.user?.id

const recordId = ref(route.query.record_id || '')

const fileUrl = ref('')
const fileName = computed(() => md5(`${ssoId}${startTime.value}`))

// WebSocket 设置
const { send } = useSocket({
  onMessage: (ws, event) => {
    try {
      const data = JSON.parse(event.data)
      if (data?.type === 'video_rtc') {
        fileUrl.value = data.data.uri
      }
    } catch (error) {
      console.error('Failed to parse message:', error)
    }
  },
})
const { start: startSpeechTranscriber, stop: stopSpeechTranscriber } = useSpeechTranscriber({
  onSentenceEnd: props.onSentenceEnd,
})

const {
  stream,
  start: startLive,
  stop: stopLive,
  startTime,
  endTime,
  duration,
  currentTime: currentLiveTime,
} = useLive({
  onStart: () => {
    console.log('开始直播')
    props.onStart && props.onStart()
    startChat()
    if (!props.isLocalUpload) {
      startSpeechTranscriber(stream.value)
    }
  },
  onRecord: async (blob) => {
    if (props.isLocalUpload) return
    const base64Data = await readBlobAsBase64(blob)
    const jsonData = JSON.stringify({
      type: 'send',
      sso_id: ssoId,
      data: { type: 'video_rtc', channel: 'rtc', data: { video: base64Data, file_name: fileName.value } },
    })
    send(jsonData)
  },
  onStop: (blob) => {
    console.log('结束直播')
    if (enabled.value) return
    props.onStop && props.onStop(blob)
    stopChat()
    handleUpdateRecord({ live_video_size: blob.size.toString() })
    // 保存录像到本地
    if (props.isLocalUpload) {
      saveAs(blob, `${fileName.value}.mp4`)
      ElMessageBox.alert('请将保存的本地视频文件上传服务端，否则会影响您的实操成绩评价！', '温馨提示')
    }
    stopSpeechTranscriber()
  },
})

watch(currentLiveTime, () => {
  currentTime.value = currentLiveTime.value
})

const record = ref({})
const handleGetRecord = async () => {
  if (!recordId.value) return
  const res = await getRecord({ id: recordId.value })
  record.value = res?.data.detail
}

watchEffect(() => {
  handleGetRecord()
})

// 更新录像记录
const handleUpdateRecord = async (params) => {
  const defaultParams = {
    live_practice_id: route.query.id,
    live_start_time: dayjs(startTime.value).format('YYYY-MM-DD HH:mm:ss'),
    live_end_time: dayjs(endTime.value).format('YYYY-MM-DD HH:mm:ss'),
    live_duration: duration.value.toString(),
    live_video_addres: fileUrl.value,
    live_info: JSON.stringify({ messages: messages.value, stats }),
    order_count: props.orderCount,
  }
  const requestParams = { ...defaultParams, ...params }
  if (!requestParams.live_practice_id) return
  const res = await saveTestRecord(requestParams)
  recordId.value = res?.data.id
}

// 上传视频
const uploading = ref(false)
let uploadLoading = null
const handleUpload = () => {
  const dialog = useFileDialog()
  dialog.open({ accept: 'video/*' })
  dialog.onChange(async ([file]) => {
    uploading.value = true
    uploadLoading = ElLoading.service({
      lock: true,
      text: '上传中',
      background: 'rgba(0, 0, 0, 0.7)',
    })
    try {
      const res = await upload(file)
      handleUpdateRecord({ id: recordId.value, live_video_addres: res, live_video_size: file.size.toString() })
      ElMessage.success('上传成功')
    } catch (error) {
      console.error(error)
      ElMessage.error('上传失败')
    } finally {
      uploading.value = false
      uploadLoading?.close()
    }
  })
}

const video = ref(null)
watchEffect(() => {
  if (video.value) {
    video.value.srcObject = stream.value
  }
})

const enabled = ref(false)
const toggleLive = () => {
  enabled.value ? startLive() : stopLive()
}
watch(enabled, toggleLive)

function start() {
  if (video.value) enabled.value = true
}
function stop() {
  if (video.value) {
    enabled.value = false
  }
}
defineExpose({ enabled, start, stop })
</script>

<template>
  <div class="live">
    <div class="live-hd">
      <p>主播：{{ userName }}</p>
      <img :src="enabled ? '/live/live2.png' : '/live/live1.png'" alt="直播状态" class="live-icon" />
    </div>
    <div class="live-bd">
      <video muted autoplay ref="video"></video>
      <LiveCover :messages="messages" :stats="stats" :viewers="viewers" v-if="enabled" />
    </div>
    <div class="live-ft">
      <el-button
        type="primary"
        size="large"
        round
        style="width: 80%"
        @click="enabled ? stop() : start()"
        v-if="!recordId">
        {{ enabled ? '结束直播' : '开始直播' }}
      </el-button>
      <el-button
        type="primary"
        size="large"
        round
        style="width: 80%; margin: 10px 0 0 0"
        :loading="uploading"
        @click="handleUpload"
        v-if="isLocalUpload && recordId"
        >上传</el-button
      >
    </div>
  </div>
</template>

<style lang="scss">
.live {
  width: 375px;

  &-hd {
    display: flex;
    justify-content: space-between;
    margin-bottom: 10px;

    .live-icon {
      height: 20px;
    }
  }

  &-bd {
    position: relative;
    height: 667px;
    border-radius: 8px;
    overflow: hidden;
    background-color: #000;
    video {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
  }

  &-ft {
    margin-top: 10px;
    text-align: center;
  }
}
</style>
