<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 } 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'
import { appendUpload } from '@/utils/oss'
import { useLiveRecord } from '../composables/useLiveRecord'
import { Check } from '@element-plus/icons-vue'

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 dialogVisible = ref(false)
const { statusText, startPolling, isPolling } = useLiveRecord()
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 isOSSUpload = true
let ossResult = null

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
    if (isOSSUpload) {
      ossResult = await appendUpload(blob, {
        name: `live/${ssoId}/${fileName.value}.mp4`,
        position: ossResult?.nextAppendPosition,
      })
      fileUrl.value = ossResult.url
    } else {
      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
  // 开始AI评分轮询
  startPolling(recordId.value)
  dialogVisible.value = true
}

// 上传视频
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>
  <el-dialog title="提示" :model-value="dialogVisible" :showClose="false" width="500px">
    <div class="modal-content">
      <template v-if="isPolling">
        <div class="progress-circle">
          <div class="spinner"></div>
        </div>
        <div class="progress-text">{{ statusText }}</div>
      </template>
      <template v-else>
        <div class="success-icon">
          <el-icon><Check /></el-icon>
        </div>
        <div class="progress-text">AI评价完成</div>
      </template>
    </div>
    <template #footer>
      <el-button auto-insert-space @click="$router.push({ path: '/live/test' })">确定</el-button>
      <el-button
        type="primary"
        auto-insert-space
        @click="$router.push({ path: '/live/test/view', query: { ...$route.query, record_id: recordId } })"
        v-if="!isPolling && recordId"
        >查看AI评价</el-button
      >
    </template>
  </el-dialog>
</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;
  }
}
.modal-content {
  text-align: center;
  padding: 1rem;
}

.progress-circle {
  width: 80px;
  height: 80px;
  margin: 0 auto 2rem;
  position: relative;
}

.spinner {
  width: 100%;
  height: 100%;
  border: 8px solid #f5f7fa;
  border-top-color: #d91f5d;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.progress-text {
  font-size: 1rem;
  color: #333;
  margin-bottom: 1rem;
  text-align: center;
}

.success-icon {
  width: 100px;
  height: 100px;
  background: #ba003f;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 2rem;

  i {
    font-size: 3rem;
    color: white;
  }
}
</style>
