<template>
  <div class="voice-selector">
    <div v-if="userVoiceCards.length === 0" class="empty-voices">
      <a-empty :image="simpleImage" description="还没有配音">
      </a-empty>
    </div>

    <div v-else class="voice-selector-with-preview">
      <a-select
        v-model:value="selectedVoiceId"
        placeholder="请选择音色"
        class="voice-select"
        :options="voiceOptions"
        @change="handleVoiceChange"
        style="width: calc(100% - 80px)"
      />

      <a-button
        class="preview-button"
        size="small"
        :disabled="!selectedVoiceId"
        :loading="previewLoadingVoiceId === selectedVoiceId"
        @click="handleSynthesize"
      >
        <template #icon>
          <SoundOutlined />
        </template>
        合成
      </a-button>
    </div>

    <!-- APlayer 播放器容器 -->
    <div v-show="audioUrl" ref="playerContainer" class="aplayer-container"></div>

    <!-- 下载按钮 -->
    <a-button
      v-show="audioUrl"
      type="link"
      size="small"
      @click="downloadAudio"
      class="download-link"
    >
      下载音频
    </a-button>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount, nextTick, watch } from 'vue'
import { Empty } from 'ant-design-vue'
import { SoundOutlined } from '@ant-design/icons-vue'
import { useVoiceCopyStore } from '@/stores/voiceCopy'
import { useTTS, TTS_PROVIDERS } from '@/composables/useTTS'
import APlayer from 'aplayer'

const props = defineProps({
  synthText: {
    type: String,
    default: ''
  },
  speechRate: {
    type: Number,
    default: 1.0
  }
})

const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE

const voiceStore = useVoiceCopyStore()

const emit = defineEmits(['select'])

let player = null
const playerContainer = ref(null)
const audioUrl = ref('')
const currentVoiceName = ref('')

// 默认封面图片（音频波形图标）
const defaultCover = `data:image/svg+xml;base64,${btoa(`
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <rect width="100" height="100" fill="#1f2937" rx="8"/>
  <g fill="#60a5fa">
    <rect x="20" y="35" width="4" height="30" rx="2">
      <animate attributeName="height" values="30;20;30" dur="0.8s" repeatCount="indefinite"/>
      <animate attributeName="y" values="35;40;35" dur="0.8s" repeatCount="indefinite"/>
    </rect>
    <rect x="30" y="30" width="4" height="40" rx="2">
      <animate attributeName="height" values="40;25;40" dur="0.6s" repeatCount="indefinite"/>
      <animate attributeName="y" values="30;37.5;30" dur="0.6s" repeatCount="indefinite"/>
    </rect>
    <rect x="40" y="25" width="4" height="50" rx="2">
      <animate attributeName="height" values="50;30;50" dur="0.7s" repeatCount="indefinite"/>
      <animate attributeName="y" values="25;35;25" dur="0.7s" repeatCount="indefinite"/>
    </rect>
    <rect x="50" y="28" width="4" height="44" rx="2">
      <animate attributeName="height" values="44;28;44" dur="0.9s" repeatCount="indefinite"/>
      <animate attributeName="y" values="28;36;28" dur="0.9s" repeatCount="indefinite"/>
    </rect>
    <rect x="60" y="32" width="4" height="36" rx="2">
      <animate attributeName="height" values="36;22;36" dur="0.5s" repeatCount="indefinite"/>
      <animate attributeName="y" values="32;39;32" dur="0.5s" repeatCount="indefinite"/>
    </rect>
    <rect x="70" y="38" width="4" height="24" rx="2">
      <animate attributeName="height" values="24;15;24" dur="0.7s" repeatCount="indefinite"/>
      <animate attributeName="y" values="38;42.5;38" dur="0.7s" repeatCount="indefinite"/>
    </rect>
  </g>
  <circle cx="50" cy="50" r="18" fill="none" stroke="#60a5fa" stroke-width="2" opacity="0.3"/>
  <path d="M44 44 L44 56 L56 50 Z" fill="#60a5fa" opacity="0.5"/>
</svg>
`.trim())}`

// 使用TTS Hook
const {
  previewLoadingVoiceId,
  playVoiceSample,
  setText,
  setSpeechRate
} = useTTS({
  provider: TTS_PROVIDERS.SILICONFLOW
})

const selectedVoiceId = ref('')

const userVoiceCards = computed(() =>
  (voiceStore.profiles || []).map(profile => ({
    id: `user-${profile.id}`,
    rawId: profile.id,
    name: profile.name || '未命名',
    category: '',
    gender: profile.gender || 'female',
    description: profile.note || '我的配音',
    fileUrl: profile.fileUrl,
    transcription: profile.transcription || '',
    source: 'user',
    voiceId: profile.voiceId
  }))
)

const voiceOptions = computed(() =>
  userVoiceCards.value.map(voice => ({
    value: voice.id,
    label: voice.name,
    data: voice
  }))
)

const handleVoiceChange = (value, option) => {
  const voice = option.data
  selectedVoiceId.value = value
  currentVoiceName.value = voice.name
  emit('select', voice)
}

const handleSynthesize = () => {
  if (!selectedVoiceId.value) return

  const voice = userVoiceCards.value.find(v => v.id === selectedVoiceId.value)
  if (!voice) return

  currentVoiceName.value = voice.name
  handlePlayVoiceSample(voice)
}

// 监听 prop 变化，更新 TTS 参数
watch(() => props.synthText, (newText) => {
  setText(newText || '')
}, { immediate: true })

watch(() => props.speechRate, (newRate) => {
  setSpeechRate(newRate)
}, { immediate: true })

/**
 * 处理音色
 */
const handlePlayVoiceSample = (voice) => {
  currentVoiceName.value = voice.name
  playVoiceSample(
    voice,
    (data) => {
      const url = data.audioUrl || data.objectUrl
      if (!url) {
        console.error('无效的音频数据格式', data)
        return
      }
      initPlayer(url)
    },
    (error) => {
      console.error('音频播放失败', error)
    },
    { autoPlay: false }  // 禁用自动播放，由 APlayer 控制
  )
}

/**
 * 初始化 APlayer
 */
const initPlayer = (url) => {
  destroyPlayer()
  audioUrl.value = url

  nextTick(() => {
    player = new APlayer({
      container: playerContainer.value,
      autoplay: true,
      theme: '#3b82f6',
      volume: 0.7,
      loop: 'none',
      audio: [{
        name: currentVoiceName.value || '语音合成',
        artist: '合成',
        url: url,
        cover: defaultCover
      }]
    })

    player.on('ended', () => {
      player.seek(0)
    })

    player.on('error', (e) => {
      console.error('APlayer 播放错误:', e)
    })
  })
}

/**
 * 下载音频
 */
const downloadAudio = () => {
  if (!audioUrl.value) return

  const filename = `${currentVoiceName.value || '语音合成'}.mp3`
  const link = document.createElement('a')
  link.href = audioUrl.value
  link.download = filename
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

/**
 * 销毁播放器
 */
const destroyPlayer = () => {
  if (player) {
    try {
      player.destroy()
    } catch (e) {
      console.error('销毁播放器失败:', e)
    }
    player = null
  }
  // 只对 blob URL 调用 revokeObjectURL
  if (audioUrl.value && audioUrl.value.startsWith('blob:')) {
    URL.revokeObjectURL(audioUrl.value)
  }
  audioUrl.value = ''
}

defineExpose({})

onMounted(async () => {
  await voiceStore.refresh()
})

onBeforeUnmount(() => {
  destroyPlayer()
})
</script>

<style scoped>
.voice-selector {
  width: 100%;
}

.empty-voices {
  padding: 16px 0;
  background: var(--color-surface);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-card);
}

/* 音色选择器和试听按钮的容器 */
.voice-selector-with-preview {
  display: flex;
  gap: 8px;
  align-items: center;
  width: 100%;
}

/* 下拉框样式 */
.voice-select {
  flex: 1;
}

/* 试听按钮样式 */
.preview-button {
  height: 32px;
  white-space: nowrap;
}

/* APlayer 容器样式 */
.aplayer-container {
  margin-top: 12px;
}

/* 下载链接样式 */
.download-link {
  margin-top: 8px;
  padding: 0;
  font-size: 12px;
}
</style>
