<script setup lang="ts">
import type { UploadProps } from 'element-plus';

import { ref } from 'vue';

import { useAppConfig } from '@easyflow/hooks';
import { $t } from '@easyflow/locales';
import { useAccessStore } from '@easyflow/stores';

import { UploadFilled } from '@element-plus/icons-vue';
import { ElIcon, ElMessage, ElUpload } from 'element-plus';

import { DocumentParseFilePolicy } from '#/utils/document-parse-file-policy';
import {
  normalizeUploadError,
  resolveUploadPath,
} from '#/utils/upload-response';

const props = defineProps({
  action: {
    type: String,
    default: '/api/v1/commons/upload',
  },
  visible: {
    type: Boolean,
    default: true,
  },
});

const emit = defineEmits(['success', 'error', 'onChange']);
const MAX_FILE_SIZE_BYTES = 100 * 1024 * 1024;
const accessStore = useAccessStore();
const headers = ref({
  'easyflow-token': accessStore.accessToken,
});
const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);

// 核心：获取ElUpload组件实例
const uploadRef = ref<InstanceType<typeof ElUpload>>();

// 上传成功回调
const handleSuccess: UploadProps['onSuccess'] = (response) => {
  try {
    emit('success', resolveUploadPath(response));
  } catch (error) {
    const normalizedError = normalizeUploadError(error);
    ElMessage.error(normalizedError.message);
    emit('error', normalizedError);
  }
};
const handleError: UploadProps['onError'] = (error) => {
  const normalizedError = normalizeUploadError(error);
  ElMessage.error(normalizedError.message);
  emit('error', normalizedError);
};

const beforeUpload: UploadProps['beforeUpload'] = async (rawFile) => {
  try {
    await DocumentParseFilePolicy.validateFiles([rawFile]);
  } catch (error: any) {
    ElMessage.warning(error?.message || $t('message.notSupported'));
    return false;
  }
  if (rawFile.size > MAX_FILE_SIZE_BYTES) {
    ElMessage.warning($t('message.upload.fileTooLarge'));
    return false;
  }
  return true;
};

// 文件状态变化回调
const handleChange: UploadProps['onChange'] = (file, fileList) => {
  emit('onChange', file, fileList);
};

// 暴露给父组件的方法：手动触发文件选择
const triggerFileSelect = () => {
  if (uploadRef.value) {
    // 调用ElUpload内部的上传按钮点击事件
    const uploadInput = uploadRef.value.$el.querySelector('input[type="file"]');
    if (uploadInput) {
      uploadInput.click(); // 触发原生文件选择框
    }
  }
};

const clearFiles = () => {
  uploadRef.value?.clearFiles?.();
};

// 对外暴露方法（父组件可通过ref调用）
defineExpose({
  clearFiles,
  triggerFileSelect,
});
</script>

<template>
  <!-- 给ElUpload添加ref引用 -->
  <ElUpload
    ref="uploadRef"
    class="upload-demo"
    drag
    :headers="headers"
    :action="`${apiURL}${props.action}`"
    :accept="DocumentParseFilePolicy.accept"
    :before-upload="beforeUpload"
    :on-success="handleSuccess"
    :on-error="handleError"
    :on-change="handleChange"
    multiple
    :style="{ display: props.visible ? 'block' : 'none' }"
  >
    <ElIcon size="48" color="hsl(var(--primary))">
      <UploadFilled />
    </ElIcon>
    <div class="flex flex-col gap-1">
      <span class="text-base">{{ $t('message.upload.title') }}</span>
      <span class="text-muted-foreground text-sm">{{
        $t('message.upload.description', {
          types: DocumentParseFilePolicy.supportedTypeLabel,
        })
      }}</span>
    </div>
  </ElUpload>
</template>
