<template>
  <BasicLayout
    title="配音管理"
    :show-back="false"
  >
    <!-- 搜索栏 -->
    <div class="search-bar">
      <a-space>
        <a-button type="primary" @click="handleCreate">
          <PlusOutlined />
          新建配音
        </a-button>
        <a-input
          v-model:value="searchParams.name"
          placeholder="搜索配音名称"
          style="width: 250px"
          @press-enter="handleSearch"
        >
          <SearchOutlined />
        </a-input>
        <a-button @click="handleSearch">查询</a-button>
        <a-button @click="handleReset">重置</a-button>
      </a-space>
    </div>

    <!-- 列表表格 -->
    <div class="table-container">
      <a-table
        :columns="columns"
        :data-source="voiceList"
        :loading="loading"
        :pagination="pagination"
        row-key="id"
        @change="handleTableChange"
      >
        <template #bodyCell="{ column, record }">
          <div v-if="column.key === 'name'" class="voice-name">
            {{ record.name || '未命名' }}
          </div>
          <a-tooltip v-else-if="column.key === 'note'" :title="record.note" placement="topLeft">
            <span class="note-text">{{ record.note || '-' }}</span>
          </a-tooltip>
          <span v-else-if="column.key === 'createTime'">
            {{ formatDateTime(record.createTime) }}
          </span>
          <a-button v-else-if="column.key === 'fileUrl'" type="link" size="small" @click="handlePlayAudio(record)">
            <PlayCircleOutlined />
            播放
          </a-button>
          <a-space v-else-if="column.key === 'actions'">
            <a-button type="link" size="small" @click="handleEdit(record)">编辑</a-button>
            <a-button type="link" size="small" danger @click="handleDelete(record)">删除</a-button>
          </a-space>
        </template>
      </a-table>
    </div>

    <!-- 表单 Modal -->
    <a-modal
      v-model:open="modalVisible"
      :title="isCreateMode ? '新建配音' : '编辑配音'"
      :width="480"
      ok-text="保存"
      cancel-text="取消"
      :confirm-loading="submitting"
      :mask-closable="false"
      centered
      @ok="handleSubmit"
      @cancel="handleCancel"
    >
      <a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
        <a-form-item label="配音名称" name="name">
          <a-input v-model:value="formData.name" placeholder="请输入配音名称" allow-clear />
        </a-form-item>

        <a-form-item
          v-if="isCreateMode"
          label="音频文件"
          name="fileId"
          :rules="[{ required: true, message: '请上传音频文件' }]"
        >
          <div class="upload-area" :class="{ 'has-file': fileList.length > 0 }">
            <a-upload-dragger
              v-model:file-list="fileList"
              :custom-request="handleCustomUpload"
              :before-upload="handleBeforeUpload"
              :max-count="1"
              :show-upload-list="false"
              accept="audio/*,.mp3,.wav,.aac,.m4a,.flac,.ogg"
              @remove="handleRemoveFile"
            >
              <template v-if="!uploadState.uploading && fileList.length === 0">
                <div class="upload-icon">
                  <CloudUploadOutlined />
                </div>
                <p class="upload-text">点击或拖拽音频文件到此区域</p>
                <p class="upload-hint-inline">支持 MP3、WAV、AAC 等格式，最大 5MB</p>
              </template>
              <template v-else-if="uploadState.uploading">
                <a-progress type="circle" :percent="50" :width="60" status="active" />
                <p class="upload-text" style="margin-top: 12px">正在上传...</p>
              </template>
              <template v-else>
                <div class="file-preview">
                  <SoundOutlined class="file-icon" />
                  <div class="file-info">
                    <span class="file-name">{{ fileList[0]?.name || '音频文件' }}</span>
                    <a-button type="link" size="small" danger @click.stop="handleRemoveFile">
                      <DeleteOutlined /> 移除
                    </a-button>
                  </div>
                </div>
              </template>
            </a-upload-dragger>
          </div>
        </a-form-item>

        <a-form-item label="备注" name="note">
          <a-textarea
            v-model:value="formData.note"
            :rows="2"
            placeholder="备注信息（选填）"
            :auto-size="{ minRows: 2, maxRows: 4 }"
            allow-clear
          />
        </a-form-item>
      </a-form>
    </a-modal>

    <audio ref="audioPlayer" style="display: none" />
  </BasicLayout>
</template>

<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { message, Modal } from 'ant-design-vue'
import { PlusOutlined, SearchOutlined, PlayCircleOutlined, CloudUploadOutlined, SoundOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import dayjs from 'dayjs'
import BasicLayout from '@/layouts/components/BasicLayout.vue'
import { MaterialService } from '@/api/material'
import { VoiceService } from '@/api/voice'
import { useUpload } from '@/composables/useUpload'
import useVoiceText from '@gold/hooks/web/useVoiceText'

// ========== 常量 ==========

const DEFAULT_FORM_DATA = {
  id: null,
  name: '',
  fileId: null,
  autoTranscribe: true,
  language: 'zh-CN',
  gender: 'female',
  note: '',
  text: '',
  fileUrl: ''
}

const MAX_FILE_SIZE = 5 * 1024 * 1024  // SiliconFlow API 限制参考音频不超过 5MB
const VALID_AUDIO_TYPES = ['audio/mpeg', 'audio/wav', 'audio/wave', 'audio/x-wav', 'audio/aac', 'audio/mp4', 'audio/flac', 'audio/ogg']
const VALID_AUDIO_EXTENSIONS = ['.mp3', '.wav', '.aac', '.m4a', '.flac', '.ogg']

// ========== 响应式数据 ==========
const loading = ref(false)
const submitting = ref(false)
const voiceList = ref([])
const modalVisible = ref(false)
const formMode = ref('create')
const formRef = ref(null)
const audioPlayer = ref(null)
const fileList = ref([])

const searchParams = reactive({
  name: '',
  pageNo: 1,
  pageSize: 10
})

const pagination = reactive({
  current: 1,
  pageSize: 10,
  total: 0,
  showSizeChanger: true,
  showTotal: (total) => `共 ${total} 条`
})

const formData = reactive({ ...DEFAULT_FORM_DATA })

// ========== Upload Hook ==========
const { state: uploadState, upload } = useUpload()

// ========== VoiceText Hook ==========
const { getVoiceText } = useVoiceText()

// ========== 计算属性 ==========
const isCreateMode = computed(() => formMode.value === 'create')

// ========== 表格配置 ==========
const columns = [
  { title: '配音名称', key: 'name', dataIndex: 'name', width: 160 },
  { title: '备注', key: 'note', dataIndex: 'note', ellipsis: true },
  { title: '创建时间', key: 'createTime', dataIndex: 'createTime', width: 180 },
  { title: '操作', key: 'actions', width: 100, fixed: 'right' }
]

// ========== 表单验证规则 ==========
const formRules = {
  name: [{ required: true, message: '请输入配音名称' }],
  fileId: [{ required: true, message: '请上传音频文件' }]
}

// ========== 工具函数 ==========
const formatDateTime = (value) => {
  if (!value) return '-'
  return dayjs(value).format('YYYY-MM-DD HH:mm:ss')
}

const fillFormData = (data) => {
  Object.assign(formData, {
    id: data.id || null,
    name: data.name || '',
    fileId: data.fileId || null,
    language: data.language || 'zh-CN',
    gender: data.gender || 'female',
    note: data.note || ''
  })
}

// ========== 数据加载 ==========
const loadVoiceList = async () => {
  loading.value = true
  try {
    const res = await VoiceService.getPage({
      pageNo: pagination.current,
      pageSize: pagination.pageSize,
      name: searchParams.name || undefined
    })
    if (res.code !== 0) return message.error(res.msg || '加载失败')

    voiceList.value = res.data.list || []
    pagination.total = res.data.total || 0
  } catch (error) {
    console.error('加载配音列表失败:', error)
    message.error('加载失败，请稍后重试')
  } finally {
    loading.value = false
  }
}

// ========== 搜索和分页 ==========
function handleSearch() {
  pagination.current = 1
  loadVoiceList()
}

function handleReset() {
  searchParams.name = ''
  pagination.current = 1
  loadVoiceList()
}

function handleTableChange(pag) {
  pagination.current = pag.current
  pagination.pageSize = pag.pageSize
  loadVoiceList()
}

// ========== CRUD 操作 ==========
function handleCreate() {
  formMode.value = 'create'
  resetForm()
  modalVisible.value = true
}

async function handleEdit(record) {
  formMode.value = 'edit'
  try {
    const res = await VoiceService.get(record.id)
    fillFormData(res.code === 0 && res.data ? res.data : record)
  } catch (error) {
    console.error('获取配音详情失败:', error)
    fillFormData(record)
  }
  modalVisible.value = true
}

function handleDelete(record) {
  Modal.confirm({
    title: '确认删除',
    content: `确定要删除配音「${record.name}」吗？此操作不可恢复。`,
    okButtonProps: { danger: true },
    centered: true,
    onOk: async function() {
      try {
        const res = await VoiceService.delete(record.id)
        if (res.code !== 0) return message.error(res.msg || '删除失败')

        message.success('删除成功')
        loadVoiceList()
      } catch (error) {
        console.error('删除失败:', error)
        message.error('删除失败，请稍后重试')
      }
    }
  })
}

// ========== 音频播放 ==========
function handlePlayAudio(record) {
  if (record.fileUrl && audioPlayer.value) {
    audioPlayer.value.src = record.fileUrl
    audioPlayer.value.play()
  } else {
    message.warning('音频文件不存在')
  }
}

// ========== 文件上传 ==========
function handleBeforeUpload(file) {
  if (file.size > MAX_FILE_SIZE) {
    message.error('文件大小不能超过 5MB')
    return false
  }

  const fileName = file.name.toLowerCase()
  const fileType = file.type.toLowerCase()

  const isValidType = VALID_AUDIO_TYPES.some(function(type) {
    return fileType.includes(type)
  }) || VALID_AUDIO_EXTENSIONS.some(function(ext) {
    return fileName.endsWith(ext)
  })

  if (!isValidType) {
    message.error('请上传音频文件（MP3、WAV、AAC、M4A、FLAC、OGG）')
    return false
  }

  return true
}

// ========== 文件上传相关 ==========
async function handleCustomUpload(options) {
  const { file, onSuccess, onError } = options

  try {
    const fileId = await upload(file, {
      fileCategory: 'voice',
      groupId: null,
      coverBase64: null,
      onSuccess: async function(id, fileUrl) {
        formData.fileId = id
        formData.fileUrl = fileUrl
        message.success('文件上传成功')
        await fetchAudioTextById(id)
        onSuccess?.({ code: 0, data: id }, file)
      },
      onError: function(error) {
        const errorMsg = error.message || '上传失败，请稍后重试'
        message.error(errorMsg)
        onError?.(error)
      }
    })

    return fileId
  } catch (error) {
    console.error('上传失败:', error)
    onError?.(error)
  }
}

// 通过fileId获取音频文本
async function fetchAudioTextById(fileId) {
  if (!fileId) return
  try {
    const res = await MaterialService.getAudioPlayUrl(fileId)
    if (res.code === 0 && res.data) {
      const rawFileUrl = res.data
      const results = await getVoiceText([{ audio_url: rawFileUrl }])
      if (results && results.length > 0) {
        const text = results[0].value
        formData.text = text
        if (text) {
          message.success('音频文本获取成功')
        }
      }
    }
  } catch (error) {
    console.error('获取音频文本失败:', error)
  }
}

function handleRemoveFile() {
  formData.fileId = null
  fileList.value = []
}

// ========== 表单操作 ==========
async function handleSubmit() {
  try {
    await formRef.value.validate()
  } catch {
    return
  }

  submitting.value = true

  const params = isCreateMode.value
    ? {
        name: formData.name,
        fileId: formData.fileId,
        autoTranscribe: formData.autoTranscribe,
        language: formData.language,
        gender: formData.gender,
        note: formData.note,
        text: formData.text
      }
    : {
        id: formData.id,
        name: formData.name,
        language: formData.language,
        gender: formData.gender,
        note: formData.note
      }

  try {
    const res = isCreateMode.value
      ? await VoiceService.create(params)
      : await VoiceService.update(params)

    if (res.code !== 0) {
      message.error(res.msg || '操作失败')
      return
    }

    message.success(isCreateMode.value ? '创建成功' : '更新成功')
    modalVisible.value = false
    loadVoiceList()
  } catch (error) {
    console.error('提交失败:', error)
    message.error('操作失败，请稍后重试')
  } finally {
    submitting.value = false
  }
}

function handleCancel() {
 modalVisible.value = false
 resetForm()
}

function resetForm() {
  Object.assign(formData, { ...DEFAULT_FORM_DATA })
  fileList.value = []
  formRef.value?.resetFields()
}

// ========== 生命周期 ==========
onMounted(function() {
  loadVoiceList()
})
</script>

<style scoped lang="less">
.search-bar {
  background: var(--color-surface);
  border-radius: var(--radius-card);
  margin-bottom: 16px;
}

.table-container {
  background: var(--color-surface);
  border-radius: var(--radius-card);
}

.voice-name {
  font-weight: 500;
  color: var(--color-text);
}

.note-text {
  color: var(--color-text-secondary);
}

// 上传区域样式
.upload-area {
  :deep(.ant-upload-drag) {
    border: 2px dashed var(--color-border, #d9d9d9);
    border-radius: 8px;
    background: var(--color-bg-container, #fafafa);
    transition: all 0.3s;
    padding: 24px 16px;

    &:hover {
      border-color: var(--color-primary, #1890ff);
      background: var(--color-primary-bg, #e6f7ff);
    }
  }

  &.has-file :deep(.ant-upload-drag) {
    border-style: solid;
    border-color: var(--color-success-border, #b7eb8f);
    background: var(--color-success-bg, #f6ffed);
  }
}

.upload-icon {
  font-size: 40px;
  color: var(--color-primary, #1890ff);
  margin-bottom: 12px;
}

.upload-text {
  font-size: 14px;
  color: var(--color-text, #333);
  margin-bottom: 4px;
}

.upload-hint-inline {
  font-size: 12px;
  color: var(--color-text-secondary, #999);
}

.file-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;

  .file-icon {
    font-size: 32px;
    color: var(--color-primary, #1890ff);
  }

  .file-info {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }

  .file-name {
    font-size: 14px;
    color: var(--color-text, #333);
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}
</style>
