import { isMatch, snakeCase, toUpper, cloneDeep, keys, pick } from 'lodash-es'
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
/**
 * 数据映射
 * @param {array} data 数据源
 * @param {object} fieldNames 自定义节点
 * @param {object} expand 拓展数据
 * @param {string} treeFieldName 子节点，如果是树型结构，传入树型结构的子节点对应的字典名
 * @param {boolean} keepOtherFields 保留其他字段
 * @returns {array}
 */
export const mapping = ({ data, fieldNames = {}, expand = {}, treeFieldName, keepOtherFields = false }) => {
    let result = []
    if (!Array.isArray(data)) return []
    if (!fieldNames) return data
    data.forEach((item, index, array) => {
        let temp = keepOtherFields ? { ...item } : {},
            record,
            filedValue

        if (treeFieldName) {
            delete temp[treeFieldName]
        }
        for (let filedKey in fieldNames) {
            filedValue = fieldNames[filedKey]
            record = item[filedValue]

            if (filedValue === treeFieldName) {
                // 树结构
                if (record && record.length) {
                    const child = mapping({
                        data: item[treeFieldName],
                        fieldNames,
                        expand,
                        treeFieldName,
                        keepOtherFields,
                    })

                    if (child && child.length) {
                        temp[filedKey] = child
                    }
                }
            } else if (filedValue instanceof Function) {
                // 函数
                temp[filedKey] = filedValue(item, index, array)
            } else {
                temp[filedKey] = typeof record !== 'undefined' && record !== '' ? record : ''
            }
        }
        temp = expand ? { ...temp, ...expand } : temp
        result.push(temp)
    })
    return result
}

/**
 * 从树型结构中查找对应数据
 * @param {array } data
 * @param {string | object} value
 * @param {function} callback
 * @param {object} fieldNames
 * @param {array} path
 */
export const findTree = (data, value, callback, fieldNames = { key: 'id', children: 'children' }, path = []) => {
    data.forEach((item, index, array) => {
        if (isObject(value) ? isMatch(item, value) : item[fieldNames.key] === value) {
            return callback(item, index, array, [...path, item])
        }
        if (item[fieldNames.children]) {
            return findTree(item[fieldNames.children], value, callback, fieldNames, [...path, item])
        }
    })
}

/**
 * 数组最深层级
 * 查找一个树型结构最多有几级
 * @param data
 * @param fieldNames
 * @return {number}
 */
export const deep = (data, fieldNames = { children: 'children' }) => {
    let result = 1
    data.forEach((item) => {
        const child = item[fieldNames.children] || []
        if (child.length) {
            let temp = deep(child, fieldNames) + 1
            result = temp > result ? temp : result
        }
    })
    return result
}

/**
 * 深度合并
 * @param object
 * @param sources
 * @return {*}
 */
export const deepMerge = (object, sources) => {
    let key
    for (key in sources) {
        object[key] =
            object[key] && object[key].toString() === '[object Object]'
                ? deepMerge(object[key], sources[key])
                : (object[key] = sources[key])
    }
    return object
}

/**
 * 时间段前缀
 * @returns
 */
export const timeFix = () => {
    const time = new Date()
    const hour = time.getHours()
    return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好'
}

/**
 * 数组合并为对象
 * @param {array} keys
 * @param {array} values
 * @param {function | array} funcs
 * @return {{}}
 */
export const zipObjectPlus = (keys = [], values = [], funcs) => {
    const result = {}
    if (Array.isArray(keys) && Array.isArray(values)) {
        keys.forEach((key, index) => {
            const func = Array.isArray(funcs) ? funcs[index] : funcs
            result[key] =
                Object.prototype.toString.call(func) === '[object Function]' ? func(values[index]) : values[index]
        })
    }
    return result
}

/**
 * 获取环境变量
 * @param {string} key
 * @returns
 */
export const env = (key, def = null) => {
    const value = import.meta.env[`VITE_${toUpper(snakeCase(key))}`] || def
    if (['true', 'false'].includes(value)) {
        return Boolean(value)
    }
    return value
}

/**
 * 树形结构转线形结构
 * @param {array} data
 * @param {object} fieldNames
 * @return {*[]}
 */
export const toList = (data = [], fieldNames = { children: 'children' }) => {
    let result = []
    if (!Array.isArray(data)) return result
    data.forEach((item) => {
        let temp = []
        result.push(item)
        if (item[fieldNames.children] && item[fieldNames.children].length) {
            let children = toList(item[fieldNames.children], fieldNames)
            if (children.length) {
                temp = children
            }
        }
        result.push(...temp)
    })
    return result
}

/**
 * 线形数据转树形数据
 * @param {array} data
 * @param {string | number} parentValue
 * @param {object} fieldNames
 * @return {*[]}
 */
export const toTree = (
    data = [],
    parentValue = '0',
    fieldNames = {
        key: 'id',
        children: 'children',
        parentKey: 'parentId',
    }
) => {
    const result = []
    data.forEach((item) => {
        if (item[fieldNames.parentKey] === parentValue) {
            let temp = item
            let children = toTree(data, item[fieldNames.key])
            if (children.length) {
                temp[fieldNames.children] = children
            }
            result.push(temp)
        }
    })
    return result
}
/**
 * 线形数据转 菜单树形数据
 * @param {array} data
 * @param {string | number} parentValue
 * @param {object} fieldNames
 * @return {*[]}
 */
export const toMenuTree = (data = []) => {
    const result = []
    data.forEach((item) => {
        let temp = {
            title: item.code,
            key: item.id,
        }
        if (item.children && item.children.length) {
            let children = toMenuTree(item.children)
            temp['children'] = children || []
        }

        result.push(temp)
    })
    return result
}

/**
 * 格式化日期
 * @param dateTime {Date} 日期
 * @param def {*} 默认值
 * @return {string}
 */
export const formatDateTime = (dateTime, def = null) => (dateTime ? dayjs(dateTime).format('YYYY-MM-DD HH:mm:ss') : def)
/**
 * 格式化utc日期
 * @param dateTime {Date} 日期
 * @return {string}
 */
export const formatUtcDateTime = (dateTime, type = 'local') => {
    dayjs.extend(utc)
    if (type === 'local') {
        // 传入local则将UTC时间转换为本地时间
        return dayjs.utc(dateTime).local().format('YYYY-MM-DD HH:mm:ss')
    } else if (type === 'UTC') {
        // 传入UTC则将时间转换为UTC时间
        return dayjs(dateTime).utc().format()
    }
}

/**
 * 格式化一天的开始时间
 * @param dateTime
 * @param def
 * @return {string}
 */
export const formatStartTimeOfDay = (dateTime, def = null) =>
    dateTime ? dayjs(dateTime).startOf('day').format('YYYY-MM-DD HH:mm:ss') : def

/**
 * 格式化一天的结束时间
 * @param dateTime
 * @param def
 * @return {string}
 */
export const formatEndTimeOfDay = (dateTime, def = null) =>
    dateTime ? dayjs(dateTime).endOf('day').format('YYYY-MM-DD HH:mm:ss') : def

/**
 * 格式化字段，无数据是返回自定义空值
 * @param data
 * @param def
 * @returns {string}
 */
export const formatField = (data, def = '-') => data ?? def

/**
 * 格式化时间区间
 * @param {array} keys
 * @param {array} values
 * @return {{}}
 */
export const formatRangeTime = (keys, values) => zipObjectPlus(keys, values, [formatStartTimeOfDay, formatEndTimeOfDay])

/**
 * 文件后缀
 */
export const suffix = (filename) => filename.split('.').pop().toLowerCase()

/**
 * 获取表单数据
 * 根据表单字段从行数据中获取对应的数据，用于回填表单
 * @param {object} record
 * @param {object} formData
 */
export const getformData = (record = {}, formData = {}) => pick(cloneDeep(record), keys(formData) || []) || {}

/**
 * 获取静态文件 url
 * @param {string} url
 * @returns
 */
export const assets = (url) => {
    return new URL(`../assets/${url}`, import.meta.url).href
}

/**
 * 是否 url
 * @param {string} value
 */
export const isUrl = (value) => new RegExp('^((https|http|ftp|rtsp|mms)?:\\/\\/)[^\\s]+', 'g').test(value)

/**
 * 是否 object
 */
export const isObject = (value) => '[object Object]' === Object.prototype.toString.call(value)

export const myTrim = (str, char, type = 'right') => {
    if (char) {
        if (type === 'left') {
            return str.replace(new RegExp('^\\' + char + '+', 'g'), '')
        } else if (type === 'right') {
            return str.replace(new RegExp('\\' + char + '+$', 'g'), '')
        }
        return str.replace(new RegExp('^\\' + char + '+|\\' + char + '+$', 'g'), '')
    }
    return str.replace(/^\s+|\s+$/g, '')
}
/**截取图片路径域名部分 */
export const spliceUrl=(fullUrl)=>{
    if(!fullUrl) return null
    const pathOnly = fullUrl.replace(/^https?:\/\/[^\/]+/, '');
    return pathOnly
}