<template>
	<u-upload :width="width" :height="height" :fileList="fileList" :accept="accept" :uploadIcon="uploadIcon"
		:uploadText="uploadText" @afterRead="afterRead" @delete="deletePic" :multiple="multiple"
		:maxCount="maxCount">
	</u-upload>
</template>

<script setup lang="ts">
import upload from '@/utils/upload';

interface FileItem {
    url: string;
}

interface UploadEvent {
    file: Array<{ url: string }>;
}

interface DeleteEvent {
    index: number;
}

interface Props {
    modelValue: string | string[] | Record<string, any> | null;
    maxCount: number;
    width: string;
    height: string;
    multiple: boolean;
    uploadText: string;
    uploadIcon: string;
    accept: string;
    isArr: boolean;
    keyUrl: string;
    isObject: boolean;
}

const props = withDefaults(defineProps<Props>(), {
    modelValue: () => [],
    maxCount: 1,
    width: '200rpx',
    height: '200rpx',
    multiple: true,
    uploadText: '点击上传',
    uploadIcon: 'plus',
    accept: 'image',
    isArr: false,
    keyUrl: '',
    isObject: false
});

const emit = defineEmits<{
    change: [value: any];
    'update:modelValue': [value: any];
}>();

const fileList = ref<FileItem[]>([]);

watch(() => props.modelValue, (ov) => {
    if (ov) {
        if (props.isObject) {
            fileList.value = [ov as FileItem];
        } else if (props.isArr) {
            if (props.keyUrl) {
                fileList.value = (ov as any[]).map(url => ({ url: url[props.keyUrl] }));
            } else {
                fileList.value = (ov as string[]).map(url => ({ url }));
            }
        } else {
            const list = (ov as string).split(',');
            fileList.value = list.map(item => ({
                url: item
            }));
        }
    }
});

const deletePic = (event: DeleteEvent) => {
    fileList.value.splice(event.index, 1);
    const urls = fileList.value.map(({ url }) => url);
    const imgs = urls.toString();
    
    if (props.isObject) {
        emit('update:modelValue', null);
        emit('change', null);
    } else if (props.isArr) {
        if (props.keyUrl) {
            emit('update:modelValue', fileList.value.map(({ url }) => ({ [props.keyUrl]: url })));
            emit('change', fileList.value.map(({ url }) => ({ [props.keyUrl]: url })));
        } else {
            emit('update:modelValue', urls);
            emit('change', urls);
        }
    } else {
        emit('update:modelValue', imgs);
        emit('change', imgs);
    }
};

const afterRead = async (event: UploadEvent) => {
    const files = event.file;
    console.log(files);
    
    // 先使用本地临时路径进行预览展示
    const startIndex = fileList.value.length;
    const tempItems = files.map(({ url }) => ({ url }));
    fileList.value = fileList.value.concat(tempItems);

    // 同步上传并在成功后用服务端URL替换临时预览
    const promises = files.map(({ url }) => upload({
        filePath: url,
        url: '/resource/oss/upload'
    }));

    try {
        const res = await Promise.all(promises);
        const uploaded: FileItem[] = [];
        res.forEach(({ code, data }) => {
            if (code === 200) {
                uploaded.push(data);
            } else {
                uploaded.push({ url: '' });
            }
        });

        // 替换对应位置的临时项为服务器返回的URL（成功的替换，失败的不动或清理）
        uploaded.forEach((item, i) => {
            const targetIndex = startIndex + i;
            if (item.url) {
                fileList.value[targetIndex] = item;
            } else {
                // 上传失败则移除该临时项
                fileList.value.splice(targetIndex, 1);
            }
        });

        const urls = fileList.value.slice(0); // 当前所有成功项
        const imgs = urls.map(({ url }) => url).toString();

        if (props.isObject) {
            emit('update:modelValue', urls[0]);
            emit('change', urls[0]);
        } else if (props.isArr) {
            if (props.keyUrl) {
                emit('update:modelValue', urls.map(({ url }) => ({ [props.keyUrl]: url })));
                emit('change', urls.map(({ url }) => ({ [props.keyUrl]: url })));
            } else {
                emit('update:modelValue', urls.map(({ url }) => url));
                emit('change', urls.map(({ url }) => url));
            }
        } else {
            emit('update:modelValue', imgs);
            emit('change', imgs);
        }
    } catch (error) {
        console.error('Upload failed:', error);
        // 全部上传失败则回滚新增的临时项
        fileList.value.splice(startIndex, tempItems.length);
    }
};
</script>

<style></style>
