<template>
    <div class="clearfix">
        <a-upload list-type="picture-card" :multiple="multiple" v-model:file-list="fileList" @preview="handlePreview"
            @change="handleChange" :customRequest="handleCustomRequest" :beforeUpload="beforeUpload"
            :accept="acceptTypes">
            <div v-if="fileList.length < fileNumber">
                <plus-outlined />
                <div class="ant-upload-text">上传</div>
            </div>
        </a-upload>
        <a-modal :open="previewVisible" :footer="null" @cancel="handleCancel">
            <img alt="example" v-if="fileType === 'img'" style="width: 100%" :src="previewImage" />
            <video v-if="fileType === 'video'" :src="previewImage" controls autoplay loop muted></video>
        </a-modal>
    </div>
</template>

<script setup>
import { ref, watch, onMounted, computed } from 'vue';
import { PlusOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import { config } from '@/config'
import apis from '@/apis'

defineOptions({
    name: 'GxUpload',
})
const fileType = ref('img')
const previewVisible = ref(false)
const previewImage = ref('')
const props = defineProps({
    modelValue: { type: Array, default: () => [] },
    headers: { type: Object, default: () => ({}) },
    multiple: { type: Boolean, default: false },
    maxSize: { type: Number, default: 10 }, // MB
    acceptTypes: { type: String, default: '*' },
    listType: { type: String, default: 'text' },
    disabled: { type: Boolean, default: false },
    uploadText: { type: String },
    fileNumber: { type: Number, default: 6 },
    width: {
        type: Number,
        default: 120,
    },
    height: {
        type: Number,
        default: 120,
    },
    customUploadHandler: {
        type: Function,
        default: null // 如果没传，就用默认的图片上传逻辑
    },
});

const emit = defineEmits(['update:modelValue', 'uploadSuccess', 'uploadError']);
const uploadUrl = config('http.apiBasic') + '/api/v1/upload'
const fileList = ref([]);

// 判断是否为Excel文件
const isExcelFile = (fileName) => {
    const excelExtensions = ['.xlsx', '.xls'];
    const fileSuffix = fileName.substring(fileName.lastIndexOf('.')).toLowerCase();
    return excelExtensions.includes(fileSuffix);
};

// 初始化文件列表
onMounted(() => {
    fileList.value = props.modelValue.map(url => ({
        uid: `preview-${Date.now()}-${Math.random()}`,
        name: url.substring(url.lastIndexOf('/') + 1),
        status: 'done',
        url: url
    }));
});

// 文件上传前校验
const beforeUpload = (file) => {
    return true;
};

const handleCancel = () => {
    previewVisible.value = false;
};

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

const handlePreview = async (file) => {
    const videoExtensions = ['.avi', '.mp4', '.mov', '.wmv', '.mkv', '.m4v'];
    const imageExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp'];
    const excelExtensions = ['.xlsx', '.xls'];

    const fileSuffix = file.name.substring(file.name.lastIndexOf('.')).toLowerCase();

    // 如果是 Excel 文件，不预览
    if (excelExtensions.includes(fileSuffix)) {
        message.info('Excel 文件不支持预览');
        return;
    }

    // 判断是图片还是视频
    if (videoExtensions.includes(fileSuffix)) {
        fileType.value = 'video';
    } else if (imageExtensions.includes(fileSuffix)) {
        fileType.value = 'img';
    } else {
        // 其他类型（如 pdf 等）也可按需处理，这里默认当图片（或不支持）
        fileType.value = 'img';
    }

    if (!file.url && !file.preview) {
        file.preview = await getBase64(file.originFileObj);
    }
    previewImage.value = file.url || file.preview;
    previewVisible.value = true;
};

// 修改handleChange方法
const handleChange = ({ file, fileList: updatedList }) => {
    // 如果是Excel文件且上传失败，不显示错误消息
    if (isExcelFile(file.name) && file.status === 'error') {
        // 从列表中移除错误项
        const filteredList = updatedList.filter(item => item.uid !== file.uid);
        fileList.value = filteredList;
        // 不显示错误消息，直接返回
        return;
    }
    
    // 处理上传成功的情况
    if (file.status === 'done') {
        const response = file.response;
        if (response && response.url) {
            // 找到当前文件项并更新URL
            const targetFile = updatedList.find(f => f.uid === file.uid);
            if (targetFile) {
                targetFile.url = response.url;
                // 如果是Excel文件，不上传成功的提示
                if (!isExcelFile(file.name)) {
                    message.success(`${file.name} 上传成功`);
                }
            }

            // 更新外部绑定值
            const urls = updatedList
                .filter(item => item.status === 'done')
                .map(item => item.url);
            emit('update:modelValue', urls);
        }
    } else if (file.status === 'removed') {
        // 更新外部绑定值
        const urls = updatedList
            .filter(item => item.status === 'done')
            .map(item => item.url);
        emit('update:modelValue', urls)
    } else if (file.status === 'uploading') {
        // 如果是Excel文件，不上传中的提示
        if (!isExcelFile(file.name)) {
            message.success(`${file.name} 上传成功`);
        }
    } else if (file.status === 'error') {
        // 非Excel文件显示错误提示
        if (!isExcelFile(file.name)) {
            message.error(`${file.name} 上传失败`);
        }
    }
};

// 修复自定义上传方法
const handleCustomRequest = async (options) => {
    const { file, onSuccess, onError } = options;

    try {
        let result;
        let fullUrl;

        if (props.customUploadHandler) {
            // 使用调用方提供的上传函数
            result = await props.customUploadHandler(file);
            // 假设返回的是完整 URL 或相对路径
            fullUrl = typeof result === 'string'
                ? result.startsWith('http') ? result : config('http.apiBasic') + result
                : result.url; // 也支持对象形式 { url: '...' }
        } else {
            // 默认走图片上传逻辑（保持兼容）
            const formData = new FormData();
            formData.append('file', file);
            const { data } = await apis.common.uploadImg(formData);
            fullUrl = config('http.apiBasic') + data;
        }

        onSuccess({
            uid: file.uid,
            name: file.name,
            status: 'done',
            url: fullUrl,
            response: { url: fullUrl }
        }, file);

        emit('uploadSuccess', fullUrl); // 或者只传 data 部分，按需调整
    } catch (err) {
        onError(err);
        // 如果是Excel文件，不显示全局错误提示
        if (!isExcelFile(file.name)) {
            message.error('上传失败');
        }
        emit('uploadError', err);
    }
};

// 同步外部v-model变化
watch(() => props.modelValue, (newVal) => {
    // 仅同步已完成的项目
    const doneFiles = fileList.value.filter(f => f.status === 'done');
    const doneUrls = doneFiles.map(f => f.url);
    // 避免循环更新
    if (JSON.stringify(newVal) !== JSON.stringify(doneUrls)) {
        fileList.value = [
            ...newVal.map(url => {
                return {
                    uid: `preview-${Date.now()}-${Math.random()}`,
                    name: url.substring(url.lastIndexOf('/') + 1),
                    status: 'done',
                    url: url
                }
            }),
            ...fileList.value.filter(f => f.status !== 'done')
        ];
    }
}, { deep: true });
</script>

<style>
/* you can make up upload button and sample style by using stylesheets */
.ant-upload-select-picture-card i {
    font-size: 32px;
    color: #999;
}

.ant-upload-select-picture-card .ant-upload-text {
    margin-top: 8px;
    color: #666;
}
</style>