<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { message, Modal } from 'ant-design-vue'
import { useVoiceCopyStore } from '@/stores/voiceCopy'
import useVoiceText from '@gold/hooks/web/useVoiceText'

const store = useVoiceCopyStore()
const profiles = computed(() => store.profiles)
const activeId = computed(() => store.activeId)
const { getVoiceText } = useVoiceText()

const form = reactive({
  id: '',
  name: '',
  language: 'zh-CN', // 简体中文
  gender: 'female',
  referenceAudio: '', // dataURL 或外链
  sampleText: '今天天气很好，我们一起去公园散步吧。',
  enhancement: 50,    // 增强强度 0-100（去噪/清晰度）
  noiseReduction: true,
  note: '',
  originalText: '',   // 原语音文本
})

const isSavingAs = ref(false)
const saveAsName = ref('')

// function generateId() {
//   return `${Date.now()}_${Math.floor(Math.random()*1e6)}`
// }

async function loadProfiles() { await store.load(); if (store.activeProfile) Object.assign(form, { ...store.activeProfile }) }

function toDataURL(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = () => resolve(reader.result)
    reader.onerror = reject
    reader.readAsDataURL(file)
  })
}

async function onUploadBefore(file) {
  try {
    const dataUrl = await toDataURL(file)
    form.referenceAudio = dataUrl
    message.success('音频已就绪（本地预处理）')
  } catch {
    message.error('读取音频失败，请重试')
  }
  return false // 阻止 antd 自动上传
}

function resetForm() {
  Object.assign(form, {
    id: '',
    name: '',
    language: 'zh-CN',
    gender: 'female',
    referenceAudio: '',
    sampleText: '今天天气很好，我们一起去公园散步吧。',
    enhancement: 50,
    noiseReduction: true,
    note: '',
    originalText: '',
  })
}

function validate() {
  if (!form.referenceAudio) {
    message.warning('请先上传或粘贴一段参考音频')
    return false
  }
  return true
}

async function transcribeOriginal() {
  const url = (form.referenceAudio || '').trim()
  if (!url) { message.warning('请先提供参考音频'); return }
  if (!/^https?:\/\//i.test(url)) {
    message.info('当前仅支持网络音频链接一键转写，请粘贴 http(s) 链接')
    return
  }
  try {
    const list = await getVoiceText([{ audio_url: url }])
    const text = Array.isArray(list) && list[0]?.value ? list[0].value : ''
    if (text) {
      form.originalText = text
      message.success('已获取原语音文本')
    } else {
      message.warning('未获取到可用文本，请稍后重试')
    }
  } catch (e) {
    console.error(e)
    message.error('转写失败，请稍后重试')
  }
}

async function saveProfile() {
  if (!validate()) return
  if (!form.id) {
    const created = await store.add({ ...form, id: '' })
    Object.assign(form, { ...created })
    message.success('已保存到本地')
  } else {
    const updated = await store.update({ ...form })
    Object.assign(form, { ...updated })
    message.success('已更新')
  }
}

function openSaveAs() {
  if (!validate()) return
  saveAsName.value = form.name ? `${form.name}-副本` : ''
  isSavingAs.value = true
}

async function confirmSaveAs() {
  const name = (saveAsName.value || '').trim()
  if (!name) {
    message.warning('请输入名称')
    return
  }
  const created = await store.duplicate({ ...form }, name)
  Object.assign(form, { ...created })
  isSavingAs.value = false
  message.success('已另存为')
}

function selectProfile(p) {
  if (!p) return
  store.select(p.id)
  Object.assign(form, { ...p })
}

function requestDelete(p) {
  Modal.confirm({
    title: '删除克隆声音',
    content: `确定删除「${p.name || '未命名'}」吗？此操作不可恢复。`,
    okText: '删除',
    okButtonProps: { danger: true },
    cancelText: '取消',
    onOk: async () => {
      await store.remove(p.id)
      if (!store.activeProfile) { resetForm() } else { Object.assign(form, { ...store.activeProfile }) }
      message.success('已删除')
    }
  })
}

onMounted(loadProfiles)
</script>

<template>
  <div class="vc-page">
    <div class="vc-grid">
      <!-- 左侧：Cosy Voice 表单 -->
      <section class="vc-left">
        <div class="vc-title">语音克隆</div>
        <div class="vc-steps">
          <span class="step">1. 上传音频</span>
          <span class="step">2. 填文本</span>
          <span class="step">3. 保存</span>
        </div>
        <a-form layout="vertical">
          <a-form-item label="名称（可选）">
            <a-input v-model:value="form.name" placeholder="给你的克隆声音起个名字" allow-clear />
          </a-form-item>

          <a-form-item label="语言">
            <a-select v-model:value="form.language" :options="[
              { value: 'zh-CN', label: '简体中文' },
              { value: 'zh-TW', label: '繁體中文' },
              { value: 'en-US', label: 'English' }
            ]" />
          </a-form-item>

          <a-form-item label="性别/音色">
            <a-radio-group v-model:value="form.gender">
              <a-radio value="female">女声（更柔和）</a-radio>
              <a-radio value="male">男声（更低沉）</a-radio>
            </a-radio-group>
          </a-form-item>

          <a-form-item label="参考音频">
            <a-upload :before-upload="onUploadBefore" :show-upload-list="false" accept="audio/*">
              <a-button type="default">选择音频文件</a-button>
            </a-upload>
            <a-input v-model:value="form.referenceAudio" placeholder="或粘贴音频外链" style="margin-top:8px" />
            <div v-if="form.referenceAudio" class="vc-audio-preview">
              <audio :src="form.referenceAudio" controls preload="metadata" />
            </div>
          </a-form-item>

          <a-form-item label="示例文本（可读一段样例，提升效果）">
            <a-textarea v-model:value="form.sampleText" :rows="3" placeholder="示例：今天天气很好，我们一起去公园散步吧。" />
          </a-form-item>

          <a-form-item label="原语音文本">
            <a-textarea v-model:value="form.originalText" :rows="4" placeholder="填写参考音频中的发音文本" />
            <div class="vc-row" style="margin-top:8px">
              <a-button @click="transcribeOriginal">一键转写</a-button>
              <div class="hint" style="margin-left:12px">仅支持网络链接</div>
            </div>
          </a-form-item>

          <div class="vc-row">
            <a-form-item label="去噪优化" style="flex:1">
              <a-switch v-model:checked="form.noiseReduction" />
            </a-form-item>
            <a-form-item label="增强强度" style="flex:2">
              <a-slider v-model:value="form.enhancement" :min="0" :max="100" />
            </a-form-item>
          </div>

          <a-form-item label="备注（可选）">
            <a-textarea v-model:value="form.note" :rows="2" />
          </a-form-item>

          <div class="vc-actions">
            <a-space>
              <a-button type="primary" @click="saveProfile">保存</a-button>
              <a-button @click="openSaveAs">另存为</a-button>
              <a-button @click="resetForm">重置</a-button>
            </a-space>
            <div class="hint" style="margin-top:6px">保存后可在右侧管理</div>
          </div>
        </a-form>
      </section>

      <!-- 右侧：已保存的克隆声音列表 -->
      <section class="vc-right">
        <div class="vc-title">已保存的克隆声音</div>
        <div v-if="!profiles.length" class="vc-empty">暂无记录，保存后会出现在这里</div>
        <ul v-else class="vc-list">
          <li v-for="p in profiles" :key="p.id" class="vc-item" :class="{ active: p.id === activeId }" @click="selectProfile(p)">
            <div class="vc-item-main">
              <div class="vc-item-name">{{ p.name || '未命名' }}</div>
              <div class="vc-item-sub">{{ p.language }} · {{ p.gender === 'female' ? '女声' : '男声' }}</div>
            </div>
            <button class="vc-item-del" @click.stop="requestDelete(p)" aria-label="删除">×</button>
          </li>
        </ul>
      </section>
    </div>

    <a-modal v-model:open="isSavingAs" title="另存为" :maskClosable="false" @ok="confirmSaveAs" @cancel="() => (isSavingAs = false)">
      <a-input v-model:value="saveAsName" placeholder="输入名称，如：小红-普通话-温柔女声" />
    </a-modal>
  </div>
</template>

<style scoped>
.vc-page { color: var(--color-text); }
.vc-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}
@media (min-width: 1024px) {
  .vc-grid { grid-template-columns: 1fr 1fr; }
}

.vc-left, .vc-right {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-inset-card);
  padding: 16px;
}

.vc-title { font-size: 14px; color: var(--color-text-secondary); margin-bottom: 8px; }
.vc-steps { display:flex; flex-wrap: wrap; gap:8px; margin-bottom: 8px; }
.vc-steps .step { font-size: 12px; color: var(--color-text-secondary); background: #161616; border: 1px solid var(--color-border); padding: 4px 8px; border-radius: 999px; }

.vc-row { display: flex; gap: 16px; }

.vc-actions { margin-top: 8px; }

.hint { font-size: 12px; color: var(--color-text-secondary); margin-top: 6px; }

.vc-audio-preview { margin-top: 8px; }
.vc-audio-preview audio { width: 100%; }

.vc-empty { color: var(--color-text-secondary); padding: 12px; }

.vc-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
.vc-item {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: 10px 12px; cursor: pointer;
  transition: background .15s ease, border-color .15s ease, transform .1s ease;
}
.vc-item:hover { background: #161616; }
.vc-item.active { border-color: var(--color-primary); }

.vc-item-main { display: flex; flex-direction: column; }
.vc-item-name { font-size: 14px; color: var(--color-text); font-weight: 600; }
.vc-item-sub { font-size: 12px; color: var(--color-text-secondary); }

.vc-item-del {
  visibility: hidden;
  width: 24px; height: 24px; border-radius: 6px;
  background: #2a2a2a; color: #fff; border: 1px solid var(--color-border);
}
.vc-item:hover .vc-item-del { visibility: visible; }
.vc-item-del:hover { background: #3a3a3a; }
</style>



