<template>
    <view class="common-file-uploader" :class="customClass">
        <!-- 编辑状态：显示可上传的文件选择器 -->
        <view v-if="editable" class="upload-wrapper">
            <uni-file-picker
              :limit="multiple ? limit : 1"
              :title="title"
              :file-mediatype="fileMediatype"
              :mode="mode"
              :auto-upload="false"
              :value="fileList"
              :disabled="disabled"
              :readonly="readonly"
              :image-styles="imageStyles"
              :list-styles="listStyles"
              :del-icon="showPreviewDelete"
              :disablePreview="disablePreview"
              :canChoose="canChoose"
              @select="handleSelect"
              @delete="handleDelete">
                <!-- 自定义上传按钮（单张图片且已有图片时显示替换） -->
                <template v-if="$slots.default || showCustomButton">
                    <slot name="default">
                        <view class="custom-upload-btn" :class="{ 'replace-btn': !multiple && fileList.length > 0 }"
                            :style="customButtonStyle">
                            <template v-if="!multiple && fileList.length > 0">
                                <text class="replace-icon">↻</text>
                                <text class="tip">{{ replaceText || t('Common.Replace') }}</text>
                            </template>
                            <template v-else>
                                <text class="plus">+</text>
<!--                                <text class="tip">{{ uploadText || t('common.upload') }}</text>-->
                            </template>
                        </view>
                    </slot>
                </template>
            </uni-file-picker>

            <!-- 上传进度 -->
            <view v-if="showProgress && uploadProgress > 0 && uploadProgress < 100" class="upload-progress"
                :style="progressStyle">
                <view class="progress-bar" :style="{ width: uploadProgress + '%' }"></view>
                <text class="progress-text">{{ uploadProgress }}%</text>
            </view>

            <!-- 上传错误提示 -->
            <view v-if="uploadError && showError" class="upload-error">
                <text class="error-text">{{ uploadError }}</text>
            </view>
        </view>

        <!-- 非编辑状态：显示图片预览 -->
        <view v-else class="image-preview" :class="previewClass">
            <!-- 单张图片预览 -->
            <template v-if="!multiple">
                <view class="single-preview">
                    <image v-if="getImageUrl(modelValue)" :src="getImageUrl(modelValue)" :mode="imageMode"
                        class="preview-image" :style="previewImageStyle" @tap="handlePreview(getImageUrl(modelValue))"
                        @error="handleImageError" :lazy-load="true" />
                    <view v-else class="no-image" :style="noImageStyle">
                        <text :style="noImageTextStyle">{{ noImageText || t('Common.NoImage') }}</text>
                    </view>
                </view>
            </template>

            <!-- 多张图片预览 -->
            <template v-else>
                <view v-if="getFileList(modelValue).length" class="image-list" :style="listContainerStyle">
                    <view v-for="(file, idx) in getFileList(modelValue)" :key="idx" class="image-item"
                        :style="imageItemStyle">
                        <image :src="getFileUrl(file)" :mode="imageMode" class="preview-image"
                            :style="previewImageStyle" @tap="handlePreview(getFilePath(file))" @error="handleImageError"
                            :lazy-load="true" />

                        <!-- 预览时的删除按钮（如果有权限） -->
                        <view v-if="showPreviewDelete && canDelete" class="preview-delete-btn" :style="deleteBtnStyle"
                            @tap.stop="handlePreviewDelete(file, idx)">
                            <text class="delete-icon">×</text>
                        </view>
                    </view>
                </view>
                <view v-else class="no-image" :style="noImageStyle">
                    <text :style="noImageTextStyle">{{ noImageText || t('Common.NoImage') }}</text>
                </view>
            </template>
        </view>
    </view>
</template>

<script setup>
import { computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import config from '@/config';
import { userToken } from '@/composables/config'
const { t } = useI18n()

const props = defineProps({
    // 基础配置
    modelValue: {
        type: [String, Array, Object],
        default: null
    },
    editable: {
        type: Boolean,
        default: false
    },
    multiple: {
        type: Boolean,
        default: false
    },
    limit: {
        type: Number,
        default: 1
    },

    // 上传配置
    title: {
        type: String,
        default: ''
    },
    fileMediatype: {
        type: String,
        default: 'image'
    },
    mode: {
        type: String,
        default: 'grid'
    },
    disabled: {
        type: Boolean,
        default: false
    },
    disablePreview: {
        type: Boolean,
        default: false
    },
    canChoose: {
        type: Boolean,
        default: false
    },
    readonly: {
        type: Boolean,
        default: false
    },

    // 上传API配置
    uploadUrl: {
        type: String,
        required: true,
        default: '/custom/bank/upload'
    },
    uploadHeaders: {
        type: Object,
        default: () => ({})
    },
    uploadName: {
        type: String,
        default: 'file'
    },
    uploadData: {
        type: Object,
        default: () => ({})
    },

    // 图片服务配置
    baseUrl: {
        type: String,
        default: config.Host80
    },
    imagePathPrefix: {
        type: String,
        default: ''
    },

    // 样式配置
    customClass: {
        type: String,
        default: ''
    },
    previewClass: {
        type: String,
        default: ''
    },

    // 尺寸配置
    imageWidth: {
        type: [String, Number],
        default: 160
    },
    imageHeight: {
        type: [String, Number],
        default: 160
    },
    imageGap: {
        type: [String, Number],
        default: 16
    },
    imageBorderRadius: {
        type: [String, Number],
        default: 8
    },

    // 图片配置
    imageMode: {
        type: String,
        default: 'aspectFill'
    },

    // 上传按钮配置
    showCustomButton: {
        type: Boolean,
        default: true
    },
    uploadText: {
        type: String,
        default: ''
    },
    replaceText: {
        type: String,
        default: ''
    },

    // 暂无图片配置
    noImageText: {
        type: String,
        default: ''
    },

    // 预览配置
    showPreviewDelete: {
        type: Boolean,
        default: false
    },
    canDelete: {
        type: Boolean,
        default: true
    },

    // 进度显示
    showProgress: {
        type: Boolean,
        default: true
    },

    // 是否自动上传
    autoUpload: {
        type: Boolean,
        default: true
    },

    // 响应数据处理函数
    responseHandler: {
        type: Function,
        default: (res) => {
            try {
                const data = typeof res === 'string' ? JSON.parse(res) : res
                return {
                    success: data.code === 200,
                    path: data.data?.path || data.data,
                    message: data.msg || '上传成功',
                    data: data
                }
            } catch (e) {
                return {
                    success: false,
                    path: null,
                    message: '解析响应失败',
                    data: null
                }
            }
        }
    },

    // uni-file-picker 的图片样式
    imageStyles: {
        type: Object,
        default: () => ({})
    },

    // uni-file-picker 的列表样式
    listStyles: {
        type: Object,
        default: () => ({})
    },

    // 自定义样式对象
    customStyles: {
        type: Object,
        default: () => ({})
    },

    // 展示错误信息
    showError: {
        type: Object,
        default: true
    }
})

const emit = defineEmits([
    'update:modelValue',
    'select',
    'delete',
    'progress',
    'success',
    'fail',
    'preview',
    'image-error',
    'preview-delete',
    'upload-start',
    'upload-complete'
])

// 上传进度
const uploadProgress = ref(0)
const uploadError = ref('')
const isUploading = ref(false)

// 文件列表（用于uni-file-picker回显）
const fileList = computed(() => {
    return getFileValue(props.modelValue)
})

// 计算样式
const imageWidthPx = computed(() => {
    return typeof props.imageWidth === 'number' ? px2rpx(props.imageWidth) : props.imageWidth
})

const imageHeightPx = computed(() => {
    return typeof props.imageHeight === 'number' ? px2rpx(props.imageHeight) : props.imageHeight
})

const imageGapPx = computed(() => {
    return typeof props.imageGap === 'number' ? px2rpx(props.imageGap) : props.imageGap
})

const imageBorderRadiusPx = computed(() => {
    return typeof props.imageBorderRadius === 'number' ? px2rpx(props.imageBorderRadius) : props.imageBorderRadius
})

// 自定义按钮样式
const customButtonStyle = computed(() => ({
    width: imageWidthPx.value,
    height: imageHeightPx.value,
    ...props.customStyles.customButton
}))

// 预览图片样式
const previewImageStyle = computed(() => ({
    width: imageWidthPx.value,
    height: imageHeightPx.value,
    borderRadius: imageBorderRadiusPx.value,
    ...props.customStyles.previewImage
}))

// 图片项样式
const imageItemStyle = computed(() => ({
    width: imageWidthPx.value,
    height: imageHeightPx.value,
    borderRadius: imageBorderRadiusPx.value,
    ...props.customStyles.imageItem
}))

// 列表容器样式
const listContainerStyle = computed(() => ({
    gap: imageGapPx.value,
    ...props.customStyles.listContainer
}))

// 暂无图片样式
const noImageStyle = computed(() => ({
    width: imageWidthPx.value,
    height: imageHeightPx.value,
    borderRadius: imageBorderRadiusPx.value,
    ...props.customStyles.noImage
}))

const noImageTextStyle = computed(() => props.customStyles.noImageText || {})
const progressStyle = computed(() => props.customStyles.progress || {})
const deleteBtnStyle = computed(() => props.customStyles.deleteBtn || {})

// 获取文件值，用于回显
const getFileValue = (value) => {
    if (!value) return props.multiple ? [] : []

    if (props.multiple) {
        if (Array.isArray(value)) {
            return value.map(item => ({
                url: getFullUrl(item.path || item),
                path: item.path || item,
                name: item.name || '图片',
                uuid: item.id || item.path || Date.now() + Math.random()
            }))
        }
        return []
    } else {
        console.log(value, [{
            url: getFullUrl(value),
            path: value,
            name: '图片',
            uuid: value
        }], 121212121);

        if (typeof value === 'string') {
            return value ? [{
                url: getFullUrl(value),
                path: value,
                name: '图片',
                uuid: value
            }] : []
        }
        if (value && value.path) {
            return [{
                url: getFullUrl(value.path),
                path: value.path,
                name: value.name || '图片',
                uuid: value.id || value.path
            }]
        }
        return []
    }
}

// 获取文件列表
const getFileList = (value) => {
    if (!value) return []

    if (props.multiple) {
        return Array.isArray(value) ? value : []
    } else {
        if (typeof value === 'string') {
            return value ? [{ path: value }] : []
        }
        return value ? [value] : []
    }
}

// 获取完整URL
const getFullUrl = (path) => {
    if (!path) return ''
    if (path.startsWith('http')) return path
    return (props.baseUrl || config.Host80) + (props.imagePathPrefix || '') + path
}

// 获取图片URL
const getImageUrl = (value) => {
    if (!value) return ''
    if (typeof value === 'string') return getFullUrl(value)
    if (value.url) return value.url
    if (value.path) return getFullUrl(value.path)
    return ''
}

// 获取文件路径
const getFilePath = (file) => {
    if (!file) return ''
    if (typeof file === 'string') return file
    return file.path || file.url || ''
}

// 获取文件URL（用于预览）
const getFileUrl = (file) => {
    if (!file) return ''
    if (typeof file === 'string') return getFullUrl(file)
    return getFullUrl(file.path || file.url || '')
}

// 处理选择文件
const handleSelect = async (e) => {
    uploadError.value = ''
    emit('select', e)

    if (props.autoUpload) {
        await uploadFiles(e.tempFiles)
    }
}

// 上传文件
const uploadFiles = async (tempFiles) => {
    if (!tempFiles || tempFiles.length === 0) return

    isUploading.value = true
    emit('upload-start')

    try {
        const uploadedPaths = []

        for (let i = 0; i < tempFiles.length; i++) {
            const file = tempFiles[i]
            uploadProgress.value = Math.round(((i) / tempFiles.length) * 100)

            const result = await uploadSingleFile(file)
            if (result.success) {
                uploadedPaths.push(result.path)
            } else {
                throw new Error(result.message)
            }

            uploadProgress.value = Math.round(((i + 1) / tempFiles.length) * 100)
        }

        // 更新modelValue
        if (props.multiple) {
            // 多张图片：合并新旧数据
            const currentValue = Array.isArray(props.modelValue) ? [...props.modelValue] : []
            const newValue = [...currentValue, ...uploadedPaths.map(path => ({ path }))]
            emit('update:modelValue', newValue)
        } else {
            // 单张图片：直接替换
            const newPath = uploadedPaths[0]
            console.log(3333, props.modelValue);

            emit('update:modelValue', newPath)
        }

        uploadProgress.value = 100
        setTimeout(() => {
            uploadProgress.value = 0
        }, 500)

        emit('upload-complete', { success: true, paths: uploadedPaths })

    } catch (error) {
        uploadError.value = error.message || '上传失败'
        uploadProgress.value = 0
        emit('upload-complete', { success: false, error: error.message })
        uni.showToast({
            title: error.message || '上传失败',
            icon: 'none'
        })
    } finally {
        isUploading.value = false
    }
}

// 上传单个文件
const uploadSingleFile = (file) => {
    return new Promise((resolve, reject) => {
        const uploadTask = uni.uploadFile({
            url: config.Host80 + props.uploadUrl,
            filePath: file.path,
            name: props.uploadName,
            header: props.uploadHeaders,
            name: 'file',
            header: {
                'Access-Token': userToken.value
            },
            formData: props.uploadData,
            success: (res) => {
                const result = props.responseHandler(res.data)
                if (result.success) {
                    resolve(result)
                } else {
                    reject(new Error(result.message))
                }
            },
            fail: (err) => {
                console.error('上传失败:', err)
                reject(new Error('网络错误，请重试'))
            }
        })
        // 监听上传进度
        uploadTask.onProgressUpdate((res) => {
            // 这里可以处理单个文件的上传进度
            console.log('单文件上传进度:', res.progress)
        })
    })
}

// 处理删除文件
const handleDelete = (e) => {
    emit('delete', e)
    // 更新modelValue
    if (props.multiple) {
        const currentValue = Array.isArray(props.modelValue) ? [...props.modelValue] : []
        const newValue = currentValue.filter((_, index) => index !== e.index)
        emit('update:modelValue', newValue)
    } else {
        emit('update:modelValue', '')
    }
}

// 处理预览
const handlePreview = (path) => {
    if (!path) return
    const urls = getFileList(props.modelValue).map(f => getFullUrl(getFilePath(f)))
    uni.previewImage({
        current: getFullUrl(path),
        urls: urls.length ? urls : [getFullUrl(path)]
    })
    emit('preview', path)
}

// 处理图片加载错误
const handleImageError = (e) => {
    console.error('图片加载失败:', e)
    emit('image-error', e)
}

// 处理预览时的删除
const handlePreviewDelete = (file, index) => {
    emit('preview-delete', { file, index })

    // 更新modelValue
    if (props.multiple) {
        const currentValue = Array.isArray(props.modelValue) ? [...props.modelValue] : []
        currentValue.splice(index, 1)
        emit('update:modelValue', currentValue)
    }
}

// 单位转换函数
const px2rpx = (px) => {
    // 假设设计稿750px，1px = 2rpx
    return px * 2 + 'rpx'
}

// 对外暴露方法
defineExpose({
    uploadFiles,
    clearError: () => uploadError.value = ''
})
</script>

<style lang="scss" scoped>
.common-file-uploader {
    width: 100%;

    .upload-wrapper {
        width: 100%;
        height: 100%;

        :deep(.uni-file-picker) {
            .file-picker__box {
                border: none;
                background: transparent;
            }
          .uni-file-picker__files{
            height: 100%;
          }
          .files-button{
            height: 100%;
          }
          .custom-upload-btn {
            width: 100%!important;
            height: 100%!important;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;

            &.replace-btn {
              background: rgba(0, 0, 0, 0.03);

              .replace-icon {
                font-size: 40px;
                color: #666;
                margin-bottom: 4px;
                transform: rotate(90deg);
              }

              .tip {
                color: #666;
              }

              &:hover {
                background: rgba(234, 32, 39, 0.05);

                .replace-icon,
                .tip {
                  color: #ea2027;
                }
              }
            }

            .plus {
              font-size: 48px;
              color: #9ca3af;
              //line-height: 1;
            }

            .tip {
              font-size: 24px;
              color: #6b7280;
            }
          }

            .file-picker__box-list {
                display: flex;
                gap: v-bind(imageGapPx);
                flex-wrap: wrap;

                .file-picker__box-item {
                    position: relative;
                    border: 1px solid #e5e7eb;
                    overflow: hidden;

                    .file-picker__box-item-image {
                        width: 100%;
                        height: 100%;
                        object-fit: cover;
                    }

                    .file-picker__box-item-close {
                        position: absolute;
                        top: 4px;
                        right: 4px;
                        width: 24px;
                        height: 24px;
                        background: rgba(0, 0, 0, 0.5);
                        border-radius: 50%;
                        display: flex;
                        align-items: center;
                        justify-content: center;

                        &::before {
                            content: '×';
                            color: #fff;
                            font-size: 28px;
                            line-height: 1;
                        }

                        .close-icon {
                            display: none;
                        }
                    }
                }
            }

            .file-picker__box-add {
                margin: 0;
                border: 2rpx dashed #d1d5db;
                background: #f9fafb;
                transition: all 0.3s;
                cursor: pointer;

                &:hover {
                    border-color: #ea2027;
                    background: #fef2f2;
                }



                .add-icon {
                    display: none;
                }
            }

            .file-picker__box-progress {
                border-radius: v-bind(imageBorderRadiusPx);
                background: rgba(0, 0, 0, 0.5);
                color: #fff;
            }
        }

        .upload-progress {
            margin-top: 8px;
            padding: 8px;
            background: #f5f5f5;
            border-radius: 4px;
            position: relative;

            .progress-bar {
                height: 4px;
                background: #ea2027;
                border-radius: 2px;
                transition: width 0.3s;
            }

            .progress-text {
                position: absolute;
                right: 8px;
                top: 8px;
                font-size: 24px;
                color: #666;
            }
        }

        .upload-error {
            margin-top: 8px;
            padding: 8px;
            background: #fee2e2;
            border-radius: 4px;

            .error-text {
                color: #dc2626;
                font-size: 24px;
            }
        }
    }

    .image-preview {
        .image-list {
            display: flex;
            gap: v-bind(imageGapPx);
            flex-wrap: wrap;

            .image-item {
                position: relative;
                overflow: hidden;
                border: 1px solid #e5e7eb;

                .preview-image {
                    width: 100%;
                    height: 100%;
                    cursor: pointer;
                }

                .preview-delete-btn {
                    position: absolute;
                    top: 4px;
                    right: 4px;
                    width: 24px;
                    height: 24px;
                    background: rgba(0, 0, 0, 0.5);
                    border-radius: 50%;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    cursor: pointer;

                    .delete-icon {
                        color: #fff;
                        font-size: 28px;
                        line-height: 1;
                    }
                }
            }
        }

        .single-preview {
            .preview-image {
                cursor: pointer;
                border: 1px solid #e5e7eb;
            }
        }

        .no-image {
            display: flex;
            align-items: center;
            justify-content: center;
            background: #f5f5f5;
            border: 1px solid #e5e7eb;

            text {
                color: #999;
                font-size: 24px;
            }
        }
    }
}
</style>