import { isObject } from '@vue/shared'
import { ElMessage, dayjs, type messageType } from 'element-plus'
import { cloneDeep } from 'lodash'
import { isArray } from './is'
import type { FieldNamesProps } from '@/components/ProTable/interface'

/**
 * @description 添加单位
 * @param {String | Number} value 值 100
 * @param {String} unit 单位 px em rem
 */
export const addUnit = (value: string | number, unit = 'px') => {
    return !Object.is(Number(value), NaN) ? `${value}${unit}` : value
}

/**
 * @description 添加单位
 * @param {unknown} value
 * @return {Boolean}
 */
export const isEmpty = (value: unknown) => {
    return value == null && typeof value == 'undefined'
}

/**
 * @description 树转数组，队列实现广度优先遍历
 * @param {Array} data  数据
 * @param {Object} props `{ children: 'children' }`
 */

export const treeToArray = (data: any[], props = { children: 'children' }) => {
    data = cloneDeep(data)
    const { children } = props
    const newData = []
    const queue: any[] = []
    data.forEach((child: any) => queue.push(child))
    while (queue.length) {
        const item: any = queue.shift()
        if (item[children]) {
            item[children].forEach((child: any) => queue.push(child))
            delete item[children]
        }
        newData.push(item)
    }
    return newData
}

/**
 * @description 数组转
 * @param {Array} data  数据
 * @param {Object} props `{ parent: 'pid', children: 'children' }`
 */

export const arrayToTree = (data: any[], props = { id: 'id', parentId: 'pid', children: 'children' }) => {
    data = cloneDeep(data)
    const { id, parentId, children } = props
    const result: any[] = []
    const map = new Map()
    data.forEach(item => {
        map.set(item[id], item)
        const parent = map.get(item[parentId])
        if (parent) {
            parent[children] = parent[children] ?? []
            parent[children].push(item)
        } else {
            result.push(item)
        }
    })
    return result
}

/**
 * 深拷贝
 * @param {any} target 需要深拷贝的对象
 * @returns {Object}
 */
export function deepClone(target: any) {
    if (typeof target !== 'object' || target === null) {
        return target
    }

    const cloneResult: any = Array.isArray(target) ? [] : {}

    for (const key in target) {
        if (Object.prototype.hasOwnProperty.call(target, key)) {
            const value = target[key]

            if (typeof value === 'object' && value !== null) {
                cloneResult[key] = deepClone(value)
            } else {
                cloneResult[key] = value
            }
        }
    }

    return cloneResult
}

/**
 * @description 获取正确的路经
 * @param {String} path  数据
 */
export function getNormalPath(path: string) {
    if (path.length === 0 || !path || path == 'undefined') {
        return path
    }
    const newPath = path.replace('//', '/')
    const length = newPath.length
    if (newPath[length - 1] === '/') {
        return newPath.slice(0, length - 1)
    }
    return newPath
}

/**
 * @description对象格式化为Query语法
 * @param { Object } params
 * @return {string} Query语法
 */
export function objectToQuery(params: Record<string, any>): string {
    let query = ''
    for (const props of Object.keys(params)) {
        const value = params[props]
        const part = encodeURIComponent(props) + '='
        if (!isEmpty(value)) {
            if (isObject(value)) {
                for (const key of Object.keys(value)) {
                    if (!isEmpty(value[key])) {
                        const params = props + '[' + key + ']'
                        const subPart = encodeURIComponent(params) + '='
                        query += subPart + encodeURIComponent(value[key]) + '&'
                    }
                }
            } else {
                query += part + encodeURIComponent(value) + '&'
            }
        }
    }
    return query.slice(0, -1)
}

/**
 * @description 时间格式化
 * @param dateTime { number } 时间戳
 * @param fmt { string } 时间格式
 * @return { string }
 */
// yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合
export const timeFormat = (dateTime: number, fmt = 'yyyy-mm-dd') => {
    // 如果为null,则格式化当前时间
    if (!dateTime) {
        dateTime = Number(new Date())
    }
    // 如果dateTime长度为10或者13，则为秒和毫秒的时间戳，如果超过13位，则为其他的时间格式
    if (dateTime.toString().length == 10) {
        dateTime *= 1000
    }
    const date = new Date(dateTime)
    let ret
    const opt: any = {
        'y+': date.getFullYear().toString(), // 年
        'm+': (date.getMonth() + 1).toString(), // 月
        'd+': date.getDate().toString(), // 日
        'h+': date.getHours().toString(), // 时
        'M+': date.getMinutes().toString(), // 分
        's+': date.getSeconds().toString() // 秒
    }
    for (const k in opt) {
        ret = new RegExp('(' + k + ')').exec(fmt)
        if (ret) {
            fmt = fmt.replace(ret[1], ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, '0'))
        }
    }
    return fmt
}

/**
 * @description 获取不重复的id
 * @param length { Number } id的长度
 * @return { String } id
 */
export const getNonDuplicateID = (length = 8) => {
    let idStr = Date.now().toString(36)
    idStr += Math.random().toString(36).substring(3, length)
    return idStr
}

/**
 * @description 单词首字母大写
 * @param  { String } str
 * @return { String } id
 */
export const firstToUpperCase = (str = '') => {
    return str.toLowerCase().replace(/( |^)[a-z]/g, $1 => $1.toUpperCase())
}

/**
 * @description ElMessage提示
 * @param  { String } message
 * @param  { String } type
 * @param  { Number } duration
 * @return { String } ElMessage
 */
export const toast = (message = '', type: messageType = 'error', duration = 1500) => {
    return ElMessage({
        message,
        type,
        duration
    })
}
interface Row {
    [key: string]: any
}
/**空判断 */
export function parseEmpty(row: Row, key: string, unit?: string) {
    if (!row) return '--'
    return unit ? (row[key] != null ? `${row[key]}${unit}` : '--') : row[key] ?? '--'
}
// 优惠券时间转换
export const parseCouponTime = (t: string) => {
    if (!t) return
    try {
        const [day, time] = t.split(' ')
        let hour = time.split(':')[0]
        hour.startsWith('0') ? (hour = hour.replace('0', '')) : ''
        return `${day} ${hour}时`
    } catch {}
    return t
}
/**循环截取文本 */
export function interceptText(text: string, interceptThreshold = 20, wrap = '\n') {
    let str = ''
    for (let i = 0; i < text.length; i += interceptThreshold) {
        str = str + text.slice(i, i + interceptThreshold) + wrap
    }
    return str
}

/**
 * 根据字节数获取文件大小，并转换成 KB、MB、GB、TB 等形式
 * @param {number} bytes - 文件的字节数
 * @returns {string} - 文件大小的字符串表示形式
 */
export function formatFileSize(bytes: number) {
    const units = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
    let size = bytes
    let unitIndex = 0

    while (size >= 1024 && unitIndex < units.length - 1) {
        size /= 1024
        unitIndex++
    }

    // 保留两位小数，四舍五入
    size = Math.round(size * 100) / 100

    return `${size} ${units[unitIndex]}`
}

/**
 * value: 数据源
 * n: 保留几位小数
 */
export function retain(value: any, n: any): string {
    if (n === 'null' || n === 'undefined' || n === 0) return value
    const tran = Math.round(value * Math.pow(10, n)) / Math.pow(10, n)
    let tranV = tran.toString()
    const newVal = tranV.indexOf('.')
    if (newVal < 0) {
        tranV += '.'
    }
    for (let i = tranV.length - tranV.indexOf('.'); i <= n; i++) {
        tranV += '0'
    }
    return tranV
}
/**
 * @description 处理 ProTable 值为数组 || 无数据
 * @param {*} callValue 需要处理的值
 * @returns {String}
 * */
export function formatValue(callValue: any) {
    // 如果当前值为数组，使用 / 拼接（根据需求自定义）
    if (isArray(callValue)) return callValue.length ? callValue.join(' / ') : '--'
    return callValue ?? '--'
}
/**
 *
 * @param {*} row 当前行数据
 * @param {*} prop 当前prop
 * @returns 返回单元格值
 */
export function handleRowAccordToProp(row: { [key: string]: any }, prop: string) {
    if (!prop.includes('.')) return row[prop] ?? '--'
    return row
}
/**
 * 处理prop
 * @param {*} prop 当前prop
 */
export function handleProp(prop: string) {
    const propArr = prop.split('.')
    if (propArr.length == 1) return prop
    return propArr[propArr.length - 1]
}
/**
 * 根据枚举列表查询当需要的数据（如果指定了 label 和 value 的 key值，会自动识别格式化）
 * @param {*} callValue 当前单元格值
 * @param {*} enumData 字典列表
 */
export function filterEnum(callValue: any, enumData?: any, fieldNames?: FieldNamesProps) {
    const value = fieldNames?.value ?? 'value'
    const label = fieldNames?.label ?? 'label'
    const children = fieldNames?.children ?? 'children'
    let filterData: { [key: string]: any } = {}
    // 判断 enumData 是否为数组
    if (Array.isArray(enumData)) filterData = findItemNested(enumData, callValue, value, children)
    return filterData ? filterData[label] : '--'
}

// 递归查找 callValue 对应的 enum 值
export function findItemNested(enumData: any, callValue: any, value: string, children: string) {
    return enumData.reduce((accumulator: any, current: any) => {
        if (accumulator) return accumulator
        if (current[value] == callValue) return current
        if (current[children]) return findItemNested(current[children], callValue, value, children)
    }, null)
}
export const shortcuts = [
    {
        text: '今天',
        value: () => {
            const start = new Date()
            const end = new Date()
            start.setHours(0, 0, 0, 0)
            end.setHours(23, 59, 59, 999)
            return [start, end]
        }
    },
    {
        text: '一周后',
        value: () => {
            const start = new Date()
            const end = new Date()
            end.setDate(end.getDate() + 7)
            start.setHours(0, 0, 0, 0)
            end.setHours(23, 59, 59, 999)
            return [start, end]
        }
    },
    {
        text: '一个月后',
        value: () => {
            const start = new Date()
            const end = new Date()
            end.setMonth(end.getMonth() + 1)
            start.setHours(0, 0, 0, 0)
            end.setHours(23, 59, 59, 999)
            return [start, end]
        }
    },
    {
        text: '三个月后',
        value: () => {
            const start = new Date()
            const end = new Date()
            end.setMonth(end.getMonth() + 3)
            start.setHours(0, 0, 0, 0)
            end.setHours(23, 59, 59, 999)
            return [start, end]
        }
    },
    {
        text: '半年后',
        value: () => {
            const start = new Date()
            const end = new Date()
            end.setMonth(end.getMonth() + 6)
            start.setHours(0, 0, 0, 0)
            end.setHours(23, 59, 59, 999)
            return [start, end]
        }
    },
    {
        text: '一年后',
        value: () => {
            const start = new Date()
            const end = new Date()
            end.setFullYear(end.getFullYear() + 1)
            start.setHours(0, 0, 0, 0)
            end.setHours(23, 59, 59, 999)
            return [start, end]
        }
    }
]
// 今天
export const getCurDate = (type: string, format = 'YYYY-MM-DD HH:mm:ss') => {
    return type == 'start' ? dayjs().startOf('day').format(format) : dayjs().endOf('day').format(format)
}
