<template>
    <view v-if="custom">
        <up-upload
            @after-read="afterRead"
            :deletable="!disabled"
            @delete="deletePic"
            :max-count="disabled ? fileList.length : maxCount"
            :accept="accept"
            multiple
            @clickPreview="clickPreview"
        >
            <slot />
        </up-upload>
    </view>
    <up-upload
        v-else
        :fileList="fileList"
        @after-read="afterRead"
        :deletable="!disabled"
        @delete="deletePic"
        :max-count="disabled ? fileList.length : maxCount"
        :accept="accept"
        multiple
        @clickPreview="clickPreview"
    />
</template>

<script setup>
import { reactive, defineProps, defineEmits, getCurrentInstance, onUnmounted } from 'vue'

/* ================= emits / props ================= */

const emit = defineEmits(['uploadCallback', 'startUploading'])

const props = defineProps({
    accept: { type: String, default: 'image' },
    maxCount: { type: [String, Number], default: 99 },
    uploadCallback: { type: Function },
    startUploading: { type: Function },
    fileList: { type: Array, default: reactive([]) },
    usetype: { type: String, default: 'default' },
    ownertable: { type: String, default: 'temporary' },
    ownerid: { type: [String, Number], default: 1 },
    disabled: { type: Boolean, default: false },
    custom: { type: Boolean, default: false },
    compressConfig: {
        type: Object,
        default: () => ({
            enable: true,
            threshold: 300 * 1024,
            targetSize: 100 * 1024,
            maxWidth: 2560,
            maxHeight: 2560,
            quality: 0.6
        })
    }
})

const { $Http } = getCurrentInstance().proxy
const deleteList = reactive([])

/* ================= 工具 ================= */

const isImage = (file) =>
    file.type?.startsWith('image/') ||
    /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(file.name || file.url)

/* ================= 压缩 ================= */

const compressImageNative = (file, quality) =>
    new Promise(resolve => {
        uni.compressImage({
            src: file.url,
            quality: Math.floor(quality * 100),
            success: res => resolve(res.tempFilePath),
            fail: () => resolve(file.url)
        })
    })

const getFileSize = (filePath) =>
    new Promise(resolve => {
        uni.getFileInfo({
            filePath,
            success: res => resolve(res.size),
            fail: () => resolve(0)
        })
    })

const compressFile = async (file) => {
    if (!props.compressConfig.enable || !isImage(file)) return file

    const size = file.size || 0
    if (size && size <= props.compressConfig.threshold) return file

    const quality = Math.min(
        Math.max((props.compressConfig.targetSize / size) * 0.5, 0.1),
        0.5
    )

    const newUrl = await compressImageNative(file, quality)
    const finalSize = await getFileSize(newUrl)

    return { ...file, url: newUrl, size: finalSize }
}

/* ================= afterRead ================= */

const afterRead = async ({ file }) => {
    emit('startUploading', file)
    const files = Array.isArray(file) ? file : [file]

    for (const item of files) {
        try {
            const processedFile = await compressFile(item)

            // ★ 修复点 1：生成稳定 uid（不影响原逻辑）
            const uid = `${Date.now()}_${Math.random()}`
            processedFile.uid = uid

            const executeUpload = (dataValue, finalUrl) => {
                const fileConf = requestType(processedFile)
                handleUploadFile(fileConf, dataValue, finalUrl, uid)

                props.fileList.push({
                    ...processedFile,
                    uid,
                    url: finalUrl,
                    status: 'uploading',
                    message: '上传中'
                })
            }

            uni.getFileSystemManager().readFile({
                filePath: processedFile.url,
                success: (data) => executeUpload(data.data, processedFile.url),
                fail: console.error
            })
        } catch (e) {
            console.error('上传失败:', e)
        }
    }
}

/* ================= 请求配置 ================= */

const requestType = (file) => {
    const ext = file.url.substring(file.url.lastIndexOf('.') + 1) || 'jpg'
    return {
        id: '10019701',
        content: {
            filename: `${Date.now()}.${ext}`,
            filetype: ext,
            parentid: uni.getStorageSync('siteP')?.appfolderid || ''
        }
    }
}

/* ================= 上传 ================= */

const handleUploadFile = (fileConfig, data, localUrl, uid) => {
    $Http.basic(fileConfig).then(res => {
        if (res.msg === '成功') {
            uploadFile(res.data, data, localUrl, uid)
        }
    })
}

const uploadFile = (res, data, localUrl, uid) => {
    uni.request({
        url: res.uploadurl,
        method: 'PUT',
        data,
        header: { 'Content-Type': 'application/octet-stream' },
        success: () => {
            $Http.basic({
                id: 10019901,
                content: { serialfilename: res.serialfilename }
            }).then(s => {
                // ★ 修复点 2：把 uid 透传下去
                handleFileLink(
                    [{ attachmentid: s.data.attachmentids[0], url: localUrl, uid }],
                    props.ownertable,
                    props.ownerid,
                    props.usetype
                )
            })
        }
    })
}

/* ================= 文件关联（核心修复在这里） ================= */

function handleFileLink(list, ownertable = 'temporary', ownerid = 1, usetype = 'default', resolve = () => {}) {
    if (!list.length) return resolve(true)

    const content = {
        ownertable,
        ownerid,
        usetype,
        attachmentids: list.map(v => v.attachmentid),
        siteid: uni.getStorageSync('userMsg').siteid
    }

    $Http.basic({
        classname: 'system.attachment.Attachment',
        method: 'createFileLink',
        content
    }).then(res => {
        resolve(res.code === '1')

        list.forEach(v => {
            // ★ 修复点 3：不再用 url，用 uid 找文件（真机关键）
            const file = props.fileList.find(s => s.uid === v.uid)
            if (file) {
                // ★ 修复点 4：不 delete，明确设置 success
                file.status = 'success'
                file.message = ''
                Object.assign(file, res.data.find(s => s.attachmentid === v.attachmentid))
            }
        })

        emit('uploadCallback', {
            fileList: props.fileList,
            attachmentids: content.attachmentids
        })
    })
}

/* ================= 业务方法（原样保留） ================= */

const isUploading = (showToast = true) => {
    const res = props.fileList.some(file => file.status === 'uploading')
    if (res && showToast) {
        uni.showToast({ title: '文件正在上传中', icon: 'none' })
    }
    return res
}

const saveFileLinks = (ownertable, ownerid, usetype = 'default') => {
    deleteList.length && deleteFile(deleteList)
    return new Promise((resolve) => {
        if (props.fileList.length) {
            return handleFileLink(props.fileList, ownertable, ownerid, usetype, resolve)
        }
        resolve(true)
    })
}

function deletePic({ file, index }) {
    uni.showModal({
        title: '提示',
        content: '确定删除？',
        success: ({ confirm }) => {
            if (!confirm) return
            if (file.ownertable === 'temporary') {
                deleteFile([file]).then(() => {
                    props.fileList.splice(index, 1)
                    emit('uploadCallback', { fileList: props.fileList })
                })
            } else {
                deleteList.push(file)
                props.fileList.splice(index, 1)
                emit('uploadCallback', { fileList: props.fileList })
            }
        }
    })
}

const deleteFile = (arr) =>
    new Promise(resolve => {
        const list = arr.filter(file => file.linksid)
        if (!list.length) return resolve(true)
        $Http.basic({
            classname: 'system.attachment.Attachment',
            method: 'deleteFileLink',
            content: { linksids: list.map(v => v.linksid) }
        }).then(res => resolve(res.code === 1))
    })

onUnmounted(() => {})

defineExpose({
    isUploading,
    handleFileLink,
    saveFileLinks,
    deleteFile
})
</script>
