<template>
  <div class="voice-input-container">
    <button
        @click="toggleSpeechInput"
        class="speech-btn"
        :class="{ 'recording': isRecording }"
    >
      <el-icon v-if="!isRecording"><Microphone /></el-icon>
      <el-icon v-else><Mute /></el-icon>
      <!-- 显示倒计时（仅录音时显示） -->
      <span v-if="isRecording" class="countdown-text">{{ countdown }}s</span>
      <div class="waveform-container" v-if="isRecording">
        <LiveWaveform
            :active="isRecording"
            :processing="false"
            :height="25"
            :barWidth="2"
            :barGap="1"
            :barRadius="1"
            :sensitivity="1.2"
        />
      </div>
    </button>

  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { Microphone, Mute } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import LiveWaveform from './LiveWaveform.vue'

// 定义props
const props = defineProps({
  // 语音识别语言，默认为中文
  lang: {
    type: String,
    default: 'zh-CN'
  },
  // 最大录音时间，默认为10秒 
  maxDuration: {
    type: Number,
    default: 10
  }
})

// 定义emit事件
const emit = defineEmits(['voiceRecognized', 'recordingStatusChanged'])

// 语音输入响应式变量
const isRecording = ref(false) // 录音状态
const recognition = ref(null) // 语音识别实例
const countdown = ref(0) // 倒计时剩余秒数
const countdownTimer = ref(null) // 倒计时定时器
const isBrowserSupported = ref(true) // 浏览器是否支持语音识别

// 检测浏览器是否支持语音识别
const checkBrowserSupport = () => {
  const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition
  if (!SpeechRecognition) {
    ElMessage.warning('当前浏览器不支持语音识别输入功能')
    isBrowserSupported.value = false
    return false
  }
  return true
}

// 初始化语音识别
const initSpeechRecognition = () => {
  if (!checkBrowserSupport()) {
    return null
  }

  const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition

  const instance = new SpeechRecognition()
  instance.lang = props.lang
  instance.interimResults = true
  // instance.continuous = true

  instance.onresult = (event) => {
    // 遍历所有结果，包括临时结果
    for (let i = event.resultIndex; i < event.results.length; i++) {
      const transcript = event.results[i][0].transcript
      // 无论是否是最终结果，实时识别结果
      emit('voiceRecognized', transcript)
      // 打印语音识别结果
      console.log('语音输入文字:', transcript)
    }
  }

  // 识别器真正开始监听时触发
  instance.onstart = () => {
    console.log('语音识别已开始监听')
  }

  // 识别器结束时清除定时器
  instance.onend = () => {
    clearInterval(countdownTimer.value)
    isRecording.value = false
    countdown.value = 0
    emit('recordingStatusChanged', false)
  }

  instance.onerror = (event) => {
    console.error('语音识别错误:', event.error)
    clearInterval(countdownTimer.value) // 出错时清除定时器
    isRecording.value = false
    emit('recordingStatusChanged', false)
    ElMessage.error('语音输入失败，请重试！', true)
    countdown.value = 0
  }

  return instance
}

// 获取浏览器信息
const getBrowserInfo = () => {
  const userAgent = window.navigator.userAgent.toLowerCase()
  if (userAgent.includes('edg')) {
    return { name: 'Edge', version: (userAgent.match(/edg\/([\d.]+)/) || [])[1] }
  }
  if (userAgent.includes('chrome')) {
    return { name: 'Chrome', version: (userAgent.match(/chrome\/([\d.]+)/) || [])[1] }
  }
  if (userAgent.includes('firefox')) {
    return { name: 'Firefox', version: (userAgent.match(/firefox\/([\d.]+)/) || [])[1] }
  }
  if (userAgent.includes('safari')) {
    return { name: 'Safari', version: (userAgent.match(/version\/([\d.]+)/) || [])[1] }
  }
  return { name: 'Unknown', version: 'Unknown' }
}

// 切换录音状态
const toggleSpeechInput = () => {
  const browser = getBrowserInfo()
  // 已知Edge支持，Chrome不支持
  if (browser.name !== 'Edge') {
    ElMessage.error('当前浏览器暂不支持语音输入功能，请使用Edge浏览器')
    isBrowserSupported.value = false
    return false
  }
  // 无论当前状态如何，先清除可能存在的旧定时器
  clearInterval(countdownTimer.value)
  countdownTimer.value = null

  if (isRecording.value) {
    // 手动停止时立即重置状态，确保在所有浏览器中波纹都能立即关闭
    isRecording.value = false
    countdown.value = 0
    emit('recordingStatusChanged', false)
    recognition.value?.stop()
  } else {
    // 初始化倒计时前再次清除定时器（防止快速点击）
    clearInterval(countdownTimer.value)
    countdown.value = props.maxDuration // 设置最大录音时间

    recognition.value = initSpeechRecognition()
    if (!recognition.value) return

    // 重新绑定onstart事件，确保系统就绪后才开始计时
    recognition.value.onstart = () => {
      console.log('语音识别已开始监听')
      // 系统真正就绪后才启动倒计时
      countdownTimer.value = setInterval(() => {
        countdown.value--
        if (countdown.value <= 0) {
          clearInterval(countdownTimer.value) // 倒计时结束清除
          recognition.value.stop()
        }
      }, 1000)
    }

    navigator.mediaDevices.getUserMedia({ audio: true })
        .then(() => {
          // 先设置UI状态，让用户知道系统正在准备
          isRecording.value = true
          emit('recordingStatusChanged', true)
          // 启动语音识别
          recognition.value.start()
        })
        .catch((err) => {
          console.error('麦克风权限获取失败:', err)
          ElMessage.warning('请允许麦克风权限以使用语音输入')
          // 出错时重置状态
          isRecording.value = false
          emit('recordingStatusChanged', false)
          countdown.value = 0
        })
  }
}

// 组件卸载时清理资源
onUnmounted(() => {
  clearInterval(countdownTimer.value)
  recognition.value?.stop()
})
</script>

<style scoped lang="scss">
@use 'sass:math';
// 定义rpx转换函数
@function rpx($px) {
  @return math.div($px, 750) * 100vw;
}
.voice-input-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: rpx(8);
}
.speech-btn {
  padding: rpx(5) rpx(10);
  background: #fff;
  border: 1px solid #ffce1b;
  border-radius: rpx(5);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: rpx(4);

  // 取消点击后的边框
  &:focus,
  &:focus-visible {
    outline: none;
    box-shadow: none;
  }

  &.recording {
    background: #ffeeba;
    border-color: #ffc107;

    .el-icon {
      color: #dc3545;
    }
  }

  .el-icon {
    font-size: rpx(8);
    color: #666;
  }
}
.waveform-container {
  // width: 100%;
  max-width: rpx(30);
}
.countdown-text {
  font-size: rpx(6);
  color: #666;
}
</style>