// src/utils/excel.ts
import { ElMessageBox, ElNotification, ElMessage } from 'element-plus'
import * as XLSX from 'xlsx'
import { saveAs } from 'file-saver'
import dayjs from 'dayjs'

/**
 * 通用 Excel 导出方法（自动拼接时间戳，避免文件重名）
 * @param options 导出配置项
 * @returns Promise<void>
 */
export const exportToExcel = async (options: {
    /** 表格数据（数组） */
    tableData: any[]
    /** 列配置（包含 label: 表头文字, prop: 字段名） */
    columns: Array<{ label: string; prop: string }>
    /** 弹窗标题（默认：导出表格） */
    title?: string
    /** 默认文件名前缀（默认：导出数据） */
    defaultFileNamePrefix?: string
    /** 时间格式化格式（默认：YYYYMMDDHHmmss，避免特殊字符） */
    timeFormat?: string
    /** 通知自定义类名（可选） */
    notificationClass?: string
    /** 工作表名称（默认：Sheet1） */
    sheetName?: string
}) => {
    // 解构配置项并设置默认值
    const {
        tableData,
        columns,
        title = '导出表格',
        defaultFileNamePrefix = '导出数据',
        // 优化：默认格式去掉空格和冒号，避免文件名非法
        timeFormat = 'YYYY-MM-DD',
        notificationClass = 'global-notification',
        sheetName = 'Sheet1'
    } = options

    try {
        // 1. 校验表格数据
        if (!tableData || tableData.length === 0) {
            ElNotification({
                message: '暂无表格数据可导出！',
                type: 'error',
                duration: 2000,
                customClass: notificationClass
            })
            return
        }

        // 2. 弹出输入框让用户输入文件名（兼容不同版本返回值）
        const rawFileName = await ElMessageBox.prompt(
            '请输入导出文件名称（会自动附带时间）', // 提示用户会附带时间
            title,
            {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                inputPlaceholder: '例如：转账明细',
                // 输入框校验：允许空输入（空输入时用默认前缀+时间）
                inputValidator: (value) => {
                    if (value && !value.trim()) {
                        return '文件名不能仅包含空格！'
                    }
                    return true
                },
                inputErrorMessage: '文件名不能仅包含空格！'
            }
        )

        // 核心修复：兼容 string / { value: string } 两种返回格式
        let fileName = ''
        if (typeof rawFileName === 'string') {
            fileName = rawFileName
        } else if (rawFileName && typeof (rawFileName as { value: string }).value === 'string') {
            fileName = (rawFileName as { value: string }).value
        }

        // 3. 处理文件名：强制拼接时间（核心修改点）
        const timeStr = dayjs().format(timeFormat)
        // 优先级：用户输入的名称 → 默认前缀；无论哪种都拼接时间
        const fileNamePrefix = fileName.trim() || defaultFileNamePrefix
        const finalFileName = `${fileNamePrefix}_${timeStr}`

        // 4. 构建带表头的Excel数据
        const exportData = tableData.map(item => {
            const row: Record<string, any> = {}
            columns.forEach(header => {
                row[header.label] = item[header.prop] || ''
            })
            return row
        })

        // 5. 创建工作表（包含表头）
        const ws = XLSX.utils.json_to_sheet(exportData, {
            header: columns.map(h => h.label), // 指定表头顺序
            skipHeader: false // 不跳过表头（关键！保证表头显示）
        })

        // 6. 创建工作簿并添加工作表
        const wb = XLSX.utils.book_new()
        XLSX.utils.book_append_sheet(wb, ws, sheetName)

        // 7. 生成Excel二进制数据
        const wbout = XLSX.write(wb, {
            bookType: 'xlsx',
            bookSST: false,
            type: 'array'
        })

        // 8. 触发下载（拼接.xlsx后缀）
        saveAs(
            new Blob([wbout], { type: 'application/octet-stream' }),
            `${finalFileName}.xlsx`
        )

        // 9. 导出成功提示
        ElNotification({
            message: `文件「${finalFileName}.xlsx」导出成功！`,
            type: 'success',
            duration: 2000,
            customClass: notificationClass
        })
    } catch (e: any) {
        // 取消导出时不提示错误
        if (e !== 'cancel') {
            ElMessage.error('导出失败，请重试！')
            console.error('Excel 导出失败：', e)
        }
    }
}