import { UploadUserFile } from 'element-plus'
import { Decimal } from 'decimal.js'
import moment from 'moment'
import service from '@/services'

/**
 * 日期格式化
 * @param value 
 * @param format 
 * @returns 
 */
export function formatDate(value?: string, format = 'YYYY-MM-DD HH:mm:ss') {
    if (value) {
        return moment(value).format(format)
    }
    return handleNoneValue()
}

/**
 * 处理价格颜色的显示
 */
export function handlePriceColor(curValue: number, preValue: number) {
    if (!curValue || curValue === preValue) {
        return ''
    } else if (curValue > preValue) {
        return 'g-color--up'
    } else {
        return 'g-color--down'
    }
}

/**
 * 处理空值的情况
 * @param value 值
 * @param suffix 后缀名
 * @returns 
 */
export function handleNoneValue<T>(value?: T, suffix = '') {
    if (value == null || String(value) === '') {
        return '--'
    }
    return value + suffix
}

/**
 * 处理0值的情况
 * @param value 值
 * @param suffix 后缀名
 * @returns 
 */
export function handleNumberValue(value: number | string = 0, suffix = '') {
    try {
        if (Number(value) === 0) {
            return '--'
        }
        return value + suffix
    }
    catch {
        return '--'
    }
}

/**
 * 从数组中创建树列表
 * @param data 
 * @param idKey 
 * @param parentIdKey 
 * @param filter 
 * @returns 
 */
export function buildTree<T>(data: T[], idKey: keyof T, parentIdKey: keyof T, filter: (node: T) => boolean = () => true) {
    const map = new Map<T[keyof T], T & { children: T[] }>()
    for (const item of data) {
        const id = item[idKey]
        map.set(id, { ...item, children: [] })
    }
    for (const item of data) {
        const id = item[idKey]
        const parentId = item[parentIdKey]
        if (parentId !== id) {
            const currentNode = map.get(id)
            const parentNode = map.get(parentId)
            if (currentNode && parentNode) {
                parentNode.children.push(currentNode)
            }
        }
    }
    const nodes = []
    for (const node of map.values()) {
        if (filter(node)) {
            nodes.push(node)
        }
    }
    return nodes
}

/**
 * 查找树形结构中某个节点
 * @param data 
 * @param value 
 * @param props 
 * @returns 
 */
export function findTreeNodeById<T extends object, K extends keyof T>(data: T[], value: T[K], props?: Partial<{ id: K, children: K }>): T | undefined {
    const { id = 'id' as K, children = 'children' as K } = props ?? {}
    for (const item of data) {
        if (item[id] === value) {
            return item
        }
        const nodes = item[children]
        if (Array.isArray(nodes)) {
            const res = findTreeNodeById(nodes, value, props)
            if (res) return res
        }
    }
    return undefined
}

/**
 * 检查某个属性值是否存在树形中
 * @param data 
 * @param value 
 * @param props 
 * @returns 
 */
export function hasValueInTree<T extends object, K extends keyof T>(data: T[], value: T[K], props?: Partial<{ id: K, children: K }>) {
    const { id = 'id' as K, children = 'children' as K } = props ?? {}
    const checkItem = (item: T) => {
        if (item[id] === value) {
            return true
        }
        const nodes = item[children]
        if (Array.isArray(nodes)) {
            return nodes.some(checkItem)
        }
        return false
    }
    return data.some(checkItem)
}

/**
 * Base64 转 Blob 对象
 * @param base64String 
 * @param contentType 
 * @returns 
 */
export function base64ToBlob(base64String: string, contentType = '') {
    let mime = contentType
    let b64Data = base64String

    if (base64String.startsWith('data:')) {
        // 移除数据URI的前缀  
        const parts = base64String.split(';base64,')
        mime = contentType || parts[0].split(':')[1].split('/')[0]
        b64Data = parts[1]
    }

    // 解码base64字符串  
    const charData = atob(b64Data)

    // 创建Uint8Array  
    const uInt8Array = new Uint8Array(charData.length)

    // 将解码后的字符串转换为字节数组  
    for (let i = 0; i < charData.length; i++) {
        uInt8Array[i] = charData.charCodeAt(i)
    }

    // 创建Blob对象  
    return new Blob([uInt8Array], { type: mime })
}

/**
 * 下载文件
 * @param blob 
 * @param fileName 
 */
export function downloadFile(blob: Blob, fileName: string) {
    const el = document.createElement('a')
    el.style.display = 'none'
    el.href = URL.createObjectURL(blob) // 转换成URL
    el.download = fileName // 自定义下载文件的名称
    document.body.appendChild(el)
    el.click()
    document.body.removeChild(el)
    URL.revokeObjectURL(el.href)
}

/**
 * 强制保留小数位，不足位数自动补零
 * @param value 
 * @param decimals 小数位
 * @param round 是否四舍五入
 * @returns 
 */
export function formatDecimal(value: number | string, decimals = 2, round = true) {
    const num = Number(value)
    if (decimals === 0) {
        // 如果不需要四舍五入，则直接截断（向下取整）
        return round ? Math.round(num).toString() : Math.floor(num).toString()
    }
    if (round) {
        return num.toFixed(decimals)
    }
    const factor = Math.pow(10, decimals)
    const truncatedNum = Math.floor(num * factor) / factor
    const [integerPart, decimalPart = ''] = truncatedNum.toString().split('.')
    // 补全小数部分到指定位数
    const zerosToAdd = decimals - decimalPart.length
    return `${integerPart}.${decimalPart}${zerosToAdd > 0 ? '0'.repeat(zerosToAdd) : ''}`
}

/**
 * 数值转换百分比
 * @param value 
 * @param decimal 保留小数位
 */
export function parsePercent(value = 0, decimal = 2, round = false) {
    if (Number.isNaN(value)) {
        return '0%'
    }
    const num = new Decimal(value).times(100)
    const res = formatDecimal(num.toNumber(), decimal, round)
    return res + '%'
}

/**
 * 数值转换万分比
 * @param value 
 * @param decimal 保留小数位
 */
export function parseTenThousand(value = 0, decimal = 2, round = false) {
    if (Number.isNaN(value)) {
        return '0‱'
    }
    const num = new Decimal(value).times(10000)
    const res = formatDecimal(num.toNumber(), decimal, round)
    return res + '‱'
}

/**
 * 转换文件路径
 * @param value 
 * @returns 
 */
export function parseFilePaths(value?: string) {
    const paths = value ? value.split(',') : []
    return paths.map((url) => {
        const urlObj = new URL(url, service.getConfig('apiUrl'))
        const name = urlObj.pathname.split('/').pop()
        return {
            name: name ?? urlObj.href,
            url: urlObj.href,
            response: {
                data: [{ filePath: value }]
            }
        }
    })
}

/**
 * 提取文件路径
 * @param uploadFiles 
 * @returns 
 */
export function extractFilePaths(uploadFiles: UploadUserFile[]) {
    return uploadFiles.map((e) => {
        const res = e.response as { data: { filePath: string }[] }
        return res.data.map((e) => e.filePath)
    }).join(',')
}

/**
 * 获取首路径完整 Url
 * @param path 
 * @returns 
 */
export function getFirstPathFullUrl(path?: string) {
    if (path) {
        const baseUrl = service.getConfig('apiUrl')
        const paths = path.split(',')
        return new URL(paths[0], baseUrl).href
    }
    return ''
}