<template>
    <div ref="uploadVideoRef" class="x-upload x-upload-video" :class="{
      'x-upload--disabled': disabled
  }">
        <a-upload
            v-if="showUploadBtn"
            :show-upload-list="false"
            :multiple="multiple"
            :before-upload="onBeforeUpload"
            :custom-request="({ file }) => customRequest(file)"
            :accept="accept"
            :disabled="disabled"
        >
            <slot>
                <div class="x-upload-btn" :class="{ 'x-upload-btn--hover': !disabled }" :style="{ width: `${width}px`, height: `${height}px` }">
                    <div class="x-upload-btn__icon">
                        <slot name="icon">
                            <plus-outlined />
                        </slot>
                    </div>
                    <div v-if="text" class="x-upload-btn__txt">
                        <slot name="text">
                            {{ text }}
                        </slot>
                    </div>
                </div>
            </slot>
        </a-upload>
        <div
            v-for="(item, index) in fileList"
            :key="item.key"
            class="x-upload-item j-upload-item"
            :class="{ 'x-upload-item--error': STATUS_ENUM.is('error', item.status) }"
            :style="{ width: `${width}px`, height: `${height}px` }"
        >
            <video :src="item.src" controls :width="width" :height="height" />

            <template v-if="['error', 'done'].includes(STATUS_ENUM.getKey(item.status))">
                <div class="x-upload-actions">
                    <div v-if="!disabled" class="x-upload-action" @click="handleRemove(index)">
                        <delete-outlined />
                    </div>
                </div>
            </template>

            <template v-else>
                <div class="x-upload-status">
                    <template v-if="STATUS_ENUM.is('uploading', item.status)">
                        <div>{{ item.percent }}%</div>
                        <a-progress :show-info="false" :stroke-width="4" :percent="item.percent" />
                    </template>
                    <template v-if="STATUS_ENUM.is('wait', item.status)">
                        <div>{{ STATUS_ENUM.getDesc(item.status) }}</div>
                        <span class="x-upload-action" @click="handleCancel(item)">取消上传</span>
                    </template>
                </div>
            </template>
        </div>
    </div>
</template>

<script setup>
import { ref, onMounted, computed, watch } from 'vue'
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import { nanoid } from 'nanoid'
import { filesize } from 'filesize'
import filesizeParser from 'filesize-parser'
import { findIndex, includes, some } from 'lodash-es'
import { STATUS_ENUM } from './config'
import apis from '@/apis'
import { config } from '@/config'
defineOptions({
    name: 'XUploadVideo',
})

defineProps({
    modelValue: {
        type: [String, Array],
        default: '',
    },
    multiple: {
        type: Boolean,
        default: false,
    },
    width: {
        type: Number,
        default: 320,
    },
    height: {
        type: Number,
        default: 180,
    },
    text: {
        type: String,
        default: '',
    },
    maxSize: {
        type: [String, Number],
        default: '50M',
    },
    accept: {
        type: String,
        default: 'video/*',
    },
    disabled: {
        type: Boolean,
        default: false,
    },
})

const emit = defineEmits(['update:modelValue'])

const fileList = ref([])
const uploadVideoRef = ref()

const loading = computed(() => fileList.value.some((o) => STATUS_ENUM.is('uploading', o.status)))
const showUploadBtn = computed(() =>true)
//const showUploadBtn = computed(() => props.multiple || !fileList.value.length)

watch(() => props.modelValue, () => init())
onMounted(() => init())

function init() {
    const currentValue = Array.isArray(props.modelValue) ? props.modelValue : [props.modelValue]
    fileList.value = currentValue.filter(Boolean).map((src) => getItem({ src }))
}

function onBeforeUpload(file) {
    const maxFileSize = typeof props.maxSize === 'number' ? props.maxSize : filesizeParser(props.maxSize)
    const isVideo = file.type.startsWith('video/')
    const isTooLarge = file.size > maxFileSize

    if (!isVideo) {
        message.error('只能上传视频文件')
        return false
    }

    if (isTooLarge) {
        message.error(`文件过大，最大不能超过 ${filesize(maxFileSize)}`)
        return false
    }

    return true
}
function customRequest(file) {
    const record = getItem({
        key: file.uid,
        status: STATUS_ENUM.getValue('wait'),
        percent: 0,
        file,
    })

    const reader = new FileReader()
    reader.onload = (e) => {
        record.src = e.target.result
        console.log('Preview loaded:', record.src)
        fileList.value = [...fileList.value] // 强制响应式更新
    }
    reader.readAsDataURL(file)

    if (props.multiple) {
        fileList.value.push(record)
    } else {
        fileList.value = [record]
    }
    console.log(loading.value)
    if (!loading.value) {
        console.log(1111)
        doUpload()
    }
}

// function customRequest(file) {
//     const record = getItem({
//         key: file.uid,
//         status: STATUS_ENUM.getValue('wait'),
//         percent: 0,
//         file,
//     })
//
//     // 预览地址设置
//     const reader = new FileReader()
//     // reader.onload = (e) => {
//     //     record.src = e.target.result
//     // }
//     reader.onload = (e) => {
//         record.src = e.target.result
//         fileList.value = [...fileList.value] // 触发响应式更新
//     }
//
//     reader.readAsDataURL(file)
//
//     if (props.multiple) {
//         fileList.value.push(record)
//         console.log('customRequest called:', file)
//
//     } else {
//         fileList.value = [record]
//     }
//
//     if (!loading.value) {
//         doUpload()
//     }
// }

async function doUpload() {
    const index = findIndex(fileList.value, { status: STATUS_ENUM.getValue('wait') })
    if (index === -1) return

    const record = fileList.value[index]
    record.status = STATUS_ENUM.getValue('uploading')

    try {
        await simulateProgress(record)

        const formData = new FormData()
        formData.append('file', record.file)

        const { success, data } = await apis.common.uploadFile(formData)

        if (config('http.code.success') === success) {
            record.percent = 100
            record.status = STATUS_ENUM.getValue('done')
            record.src = data.url || record.src
            emitValue()
            await doUpload() // 上传下一个
        } else {
            record.status = STATUS_ENUM.getValue('error')
            message.error('上传失败，请重试')
        }
    } catch (err) {
        record.status = STATUS_ENUM.getValue('error')
        message.error('上传异常，请检查网络或稍后再试')
    }
}


async function simulateProgress(record) {
    return new Promise((resolve) => {
        let percent = 0
        const interval = setInterval(() => {
            percent += Math.random() * 10 + 5
            if (percent >= 95) {
                clearInterval(interval)
                record.percent = 95
                resolve()
            } else {
                record.percent = Math.floor(percent)
            }
        }, 200)
    })
}
function handleRemove(index) {
    fileList.value.splice(index, 1)
    emitValue()
}

function handleCancel({ key }) {
    const index = fileList.value.findIndex((o) => o.key === key)
    fileList.value.splice(index, 1)
}

function getItem(obj) {
    return {
        key: nanoid(),
        src: '',
        status: STATUS_ENUM.getValue('done'),
        percent: 100,
        ...obj,
    }
}

function emitValue() {
    const value = props.multiple
        ? fileList.value.filter((item) => STATUS_ENUM.is('done', item.status)).map((item) => item?.src ?? item)
        : (fileList.value[0]?.src ?? '') || ''
    emit('update:modelValue', value)
}
</script>

<style lang="less" scoped>
.x-upload {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;

    &--disabled {
        .x-upload-btn {
            opacity: 0.5;
            cursor: not-allowed;
        }
    }

    &-btn {
        border: 1px dashed #ccc;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        transition: all 0.2s;
        border-radius: 8px;

        &--hover:hover {
            border-color: #1890ff;
            color: #1890ff;
        }

        &__icon {
            font-size: 20px;
        }

        &__txt {
            margin-top: 8px;
        }
    }

    &-item {
        position: relative;
        background: #f5f5f5;
        overflow: hidden;
        border-radius: 8px;

        video {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        &:hover {
            .x-upload-actions {
                opacity: 1;
            }
        }

        &--error::before {
            content: '';
            position: absolute;
            width: 100%;
            height: 100%;
            border: 1px dashed red;
            z-index: 2;
        }
    }

    &-actions {
        position: absolute;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 4px;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
        background: rgba(0, 0, 0, 0.25);
        opacity: 0;
        transition: all 0.15s;
    }

    &-action {
        min-width: 24px;
        height: 24px;
        color: #fff;
        border-radius: 2px;
        cursor: pointer;
        background: rgba(0, 0, 0, 0.3);
        padding: 0 4px;
        display: flex;
        align-items: center;
        justify-content: center;

        &:hover {
            background: rgba(0, 0, 0, 0.5);
        }
    }

    &-status {
        position: absolute;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        background: rgba(0, 0, 0, 0.4);
        color: #fff;
        flex-direction: column;
    }
}
</style>
