<template>
  <div class="audio-upload-container">
    <el-upload
      ref="audioUploadRef"
      :auto-upload="false"
      :show-file-list="false"
      :accept="fileAccept"
      :on-change="handleFileChange"
      :disabled="disabled || uploading"
    >
      <el-button type="primary" :icon="Upload" :disabled="disabled || uploading">
        {{ uploading ? '上传中...' : '选择音频文件' }}
      </el-button>
    </el-upload>

    <!-- 上传提示 -->
    <div v-if="showTip" class="el-upload__tip">
      支持格式: <b style="color: #f56c6c">{{ fileType.join('、') }}</b>,
      大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
    </div>

    <!-- 上传进度 -->
    <div v-if="uploading" class="upload-progress">
      <el-progress :percentage="uploadPercent" :status="uploadStatus" />
      <span class="progress-text">{{ progressText }}</span>
    </div>

    <!-- 已上传文件显示 -->
    <div v-if="currentFile && !uploading" class="file-preview">
      <div class="file-info">
        <el-icon class="file-icon"><Headset /></el-icon>
        <span class="file-name">{{ currentFile.name }}</span>
      </div>
      <div class="file-actions">
        <el-button v-if="currentFile.url" type="primary" link @click="previewAudio">试听</el-button>
        <el-button v-if="!disabled" type="danger" link @click="handleRemove">删除</el-button>
      </div>
    </div>

    <!-- 音频预览对话框 -->
    <el-dialog v-model="previewVisible" title="音频预览" width="500px" append-to-body>
      <audio v-if="previewUrl" :src="previewUrl" controls style="width: 100%"></audio>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, getCurrentInstance, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { Upload, Headset } from '@element-plus/icons-vue';
import { createCosInstance, getCosConfig } from '@/api/inspection/cos';
import type { CosUploadProgress } from '@/api/inspection/cos/types';
import type { ComponentInternalInstance } from 'vue';

interface Props {
  modelValue?: string; // v-model绑定的URL
  fileSize?: number; // 文件大小限制(MB)
  fileType?: string[]; // 支持的文件类型
  disabled?: boolean; // 是否禁用
  showTip?: boolean; // 是否显示提示
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: '',
  fileSize: 10,
  fileType: () => ['mp3', 'wav', 'm4a', 'aac', 'ogg'],
  disabled: false,
  showTip: true
});

const emit = defineEmits<{
  'update:modelValue': [value: string];
  'upload-success': [url: string];
  'upload-error': [error: any];
}>();

const { proxy } = getCurrentInstance() as ComponentInternalInstance;

const audioUploadRef = ref();
const currentFile = ref<{ name: string; url?: string } | null>(null);
const uploading = ref(false);
const uploadPercent = ref(0);
const uploadStatus = ref<'success' | 'exception' | 'warning'>('success');
const previewVisible = ref(false);
const previewUrl = ref('');

// COS配置
const cosConfig = ref<{ bucket: string; region: string }>();

// 计算accept属性
const fileAccept = computed(() => props.fileType.map((type) => `.${type}`).join(','));

// 进度文本
const progressText = computed(() => {
  if (uploadPercent.value < 100) {
    return `正在上传: ${uploadPercent.value}%`;
  }
  return '上传完成';
});

// 监听modelValue变化
watch(
  () => props.modelValue,
  (url) => {
    if (url) {
      // 从URL提取文件名
      const fileName = url.substring(url.lastIndexOf('/') + 1);
      currentFile.value = { name: decodeURIComponent(fileName), url };
    } else {
      currentFile.value = null;
    }
  },
  { immediate: true }
);

// 初始化COS配置
const initCosConfig = async () => {
  try {
    const res = await getCosConfig();
    cosConfig.value = res.data;
  } catch (error) {
    console.error('获取COS配置失败:', error);
  }
};

// 组件挂载时初始化
onMounted(() => {
  initCosConfig();
});

// 文件选择变化
const handleFileChange = (file: any) => {
  // 校验文件类型
  const fileName = file.name;
  const fileExt = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
  if (!props.fileType.includes(fileExt)) {
    proxy?.$modal.msgError(`文件格式不正确,请上传${props.fileType.join('、')}格式的音频文件!`);
    return;
  }

  // 校验文件大小
  const fileSizeMB = file.size / 1024 / 1024;
  if (fileSizeMB > props.fileSize) {
    proxy?.$modal.msgError(`文件大小不能超过${props.fileSize}MB!`);
    return;
  }

  // 开始上传
  uploadToCos(file.raw, fileName);
};

// 上传到COS
const uploadToCos = async (file: File, fileName: string) => {
  if (!cosConfig.value) {
    ElMessage.error('COS配置未加载,请稍后重试');
    return;
  }

  uploading.value = true;
  uploadPercent.value = 0;
  uploadStatus.value = 'success';

  try {
    const cos = createCosInstance();
    const timestamp = Date.now();
    const key = `audio/${timestamp}_${fileName}`;

    cos.uploadFile(
      {
        Bucket: cosConfig.value.bucket,
        Region: cosConfig.value.region,
        Key: key,
        Body: file,
        SliceSize: 1024 * 1024 * 100, // 大于100MB使用分块上传
        onProgress: (progressData: CosUploadProgress) => {
          uploadPercent.value = Math.round(progressData.percent * 100);
        }
      },
      (err: any, data: any) => {
        uploading.value = false;

        if (err) {
          uploadStatus.value = 'exception';
          ElMessage.error('上传失败: ' + err.message);
          emit('upload-error', err);
          return;
        }

        // 上传成功
        const url = 'https://' + data.Location;
        currentFile.value = { name: fileName, url };
        emit('update:modelValue', url);
        emit('upload-success', url);
        ElMessage.success('上传成功');
      }
    );
  } catch (error) {
    uploading.value = false;
    uploadStatus.value = 'exception';
    ElMessage.error('上传失败: ' + error);
    emit('upload-error', error);
  }
};

// 删除文件
const handleRemove = () => {
  currentFile.value = null;
  uploadPercent.value = 0;
  emit('update:modelValue', '');
};

// 预览音频
const previewAudio = () => {
  if (currentFile.value?.url) {
    previewUrl.value = currentFile.value.url;
    previewVisible.value = true;
  }
};
</script>

<style lang="scss" scoped>
.audio-upload-container {
  .el-upload__tip {
    margin-top: 8px;
    font-size: 12px;
    color: #606266;
  }

  .upload-progress {
    margin-top: 12px;

    .progress-text {
      display: block;
      margin-top: 8px;
      font-size: 12px;
      color: #606266;
    }
  }

  .file-preview {
    margin-top: 12px;
    padding: 8px 12px;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    display: flex;
    justify-content: space-between;
    align-items: center;

    .file-info {
      display: flex;
      align-items: center;
      flex: 1;

      .file-icon {
        font-size: 20px;
        margin-right: 8px;
        color: #409eff;
      }

      .file-name {
        font-size: 14px;
        color: #606266;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
    }

    .file-actions {
      display: flex;
      gap: 8px;
    }
  }
}
</style>
