/*
 * @Descripttion: 工具集
 * @version: 2.0
 * @LastEditors: sakuya
 * @LastEditTime: 2026年1月15日
 */

import CryptoJS from 'crypto-js'
import sysConfig from '@/config'

const tool = {}

/**
 * 检查是否为有效的值（非null、非undefined、非空字符串、非空数组、非空对象）
 * @param {*} value - 要检查的值
 * @returns {boolean}
 */
tool.isValid = function (value) {
	if (value === null || value === undefined) {
		return false
	}
	if (typeof value === 'string' && value.trim() === '') {
		return false
	}
	if (Array.isArray(value) && value.length === 0) {
		return false
	}
	if (typeof value === 'object' && Object.keys(value).length === 0) {
		return false
	}
	return true
}

/**
 * 防抖函数
 * @param {Function} func - 要执行的函数
 * @param {number} wait - 等待时间（毫秒）
 * @param {boolean} immediate - 是否立即执行
 * @returns {Function}
 */
tool.debounce = function (func, wait = 300, immediate = false) {
	let timeout
	return function (...args) {
		const context = this
		clearTimeout(timeout)
		if (immediate && !timeout) {
			func.apply(context, args)
		}
		timeout = setTimeout(() => {
			timeout = null
			if (!immediate) {
				func.apply(context, args)
			}
		}, wait)
	}
}

/**
 * 节流函数
 * @param {Function} func - 要执行的函数
 * @param {number} wait - 等待时间（毫秒）
 * @param {Object} options - 配置选项 { leading: boolean, trailing: boolean }
 * @returns {Function}
 */
tool.throttle = function (func, wait = 300, options = {}) {
	let timeout
	let previous = 0
	const { leading = true, trailing = true } = options

	return function (...args) {
		const context = this
		const now = Date.now()

		if (!previous && !leading) {
			previous = now
		}

		const remaining = wait - (now - previous)

		if (remaining <= 0 || remaining > wait) {
			if (timeout) {
				clearTimeout(timeout)
				timeout = null
			}
			previous = now
			func.apply(context, args)
		} else if (!timeout && trailing) {
			timeout = setTimeout(() => {
				previous = leading ? Date.now() : 0
				timeout = null
				func.apply(context, args)
			}, remaining)
		}
	}
}

/**
 * 深拷贝对象（支持循环引用）
 * @param {*} obj - 要拷贝的对象
 * @param {WeakMap} hash - 用于检测循环引用
 * @returns {*}
 */
tool.deepClone = function (obj, hash = new WeakMap()) {
	if (obj === null || typeof obj !== 'object') {
		return obj
	}

	if (hash.has(obj)) {
		return hash.get(obj)
	}

	const clone = Array.isArray(obj) ? [] : {}
	hash.set(obj, clone)

	for (const key in obj) {
		if (Object.prototype.hasOwnProperty.call(obj, key)) {
			clone[key] = tool.deepClone(obj[key], hash)
		}
	}

	return clone
}

/* localStorage */
tool.data = {
	set(key, data, datetime = 0) {
		//加密
		if (sysConfig.LS_ENCRYPTION == 'AES') {
			data = tool.crypto.AES.encrypt(JSON.stringify(data), sysConfig.LS_ENCRYPTION_key)
		}
		let cacheValue = {
			content: data,
			datetime: parseInt(datetime) === 0 ? 0 : new Date().getTime() + parseInt(datetime) * 1000,
		}
		return localStorage.setItem(key, JSON.stringify(cacheValue))
	},
	get(key) {
		try {
			const value = JSON.parse(localStorage.getItem(key))
			if (value) {
				let nowTime = new Date().getTime()
				if (nowTime > value.datetime && value.datetime != 0) {
					localStorage.removeItem(key)
					return null
				}
				//解密
				if (sysConfig.LS_ENCRYPTION == 'AES') {
					value.content = JSON.parse(tool.crypto.AES.decrypt(value.content, sysConfig.LS_ENCRYPTION_key))
				}
				return value.content
			}
			return null
		} catch {
			return null
		}
	},
	remove(key) {
		return localStorage.removeItem(key)
	},
	clear() {
		return localStorage.clear()
	},
}

/*sessionStorage*/
tool.session = {
	set(table, settings) {
		const _set = JSON.stringify(settings)
		return sessionStorage.setItem(table, _set)
	},
	get(table) {
		const data = sessionStorage.getItem(table)
		try {
			return JSON.parse(data)
		} catch {
			return null
		}
	},
	remove(table) {
		return sessionStorage.removeItem(table)
	},
	clear() {
		return sessionStorage.clear()
	},
}

/*cookie*/
tool.cookie = {
	/**
	 * 设置cookie
	 * @param {string} name - cookie名称
	 * @param {string} value - cookie值
	 * @param {Object} config - 配置选项
	 */
	set(name, value, config = {}) {
		const cfg = {
			expires: null,
			path: null,
			domain: null,
			secure: false,
			httpOnly: false,
			sameSite: 'Lax',
			...config,
		}
		let cookieStr = `${name}=${encodeURIComponent(value)}`
		if (cfg.expires) {
			const exp = new Date()
			exp.setTime(exp.getTime() + parseInt(cfg.expires) * 1000)
			cookieStr += `;expires=${exp.toUTCString()}`
		}
		if (cfg.path) {
			cookieStr += `;path=${cfg.path}`
		}
		if (cfg.domain) {
			cookieStr += `;domain=${cfg.domain}`
		}
		if (cfg.secure) {
			cookieStr += `;secure`
		}
		if (cfg.sameSite) {
			cookieStr += `;SameSite=${cfg.sameSite}`
		}
		document.cookie = cookieStr
	},
	/**
	 * 获取cookie
	 * @param {string} name - cookie名称
	 * @returns {string|null}
	 */
	get(name) {
		const arr = document.cookie.match(new RegExp('(^| )' + name + '=([^;]*)(;|$)'))
		if (arr != null) {
			return decodeURIComponent(arr[2])
		}
		return null
	},
	/**
	 * 删除cookie
	 * @param {string} name - cookie名称
	 */
	remove(name) {
		const exp = new Date()
		exp.setTime(exp.getTime() - 1)
		document.cookie = `${name}=;expires=${exp.toUTCString()}`
	},
}

/* Fullscreen */
/**
 * 切换全屏状态
 * @param {HTMLElement} element - 要全屏的元素
 */
tool.screen = function (element) {
	const isFull = !!(document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement || document.fullscreenElement)
	if (isFull) {
		if (document.exitFullscreen) {
			document.exitFullscreen()
		} else if (document.msExitFullscreen) {
			document.msExitFullscreen()
		} else if (document.mozCancelFullScreen) {
			document.mozCancelFullScreen()
		} else if (document.webkitExitFullscreen) {
			document.webkitExitFullscreen()
		}
	} else {
		if (element.requestFullscreen) {
			element.requestFullscreen()
		} else if (element.msRequestFullscreen) {
			element.msRequestFullscreen()
		} else if (element.mozRequestFullScreen) {
			element.mozRequestFullScreen()
		} else if (element.webkitRequestFullscreen) {
			element.webkitRequestFullscreen()
		}
	}
}

/* 复制对象（浅拷贝） */
/**
 * 浅拷贝对象
 * @param {*} obj - 要拷贝的对象
 * @returns {*} - 拷贝后的对象
 */
tool.objCopy = function (obj) {
	if (obj === null || typeof obj !== 'object') {
		return obj
	}
	return JSON.parse(JSON.stringify(obj))
}

/* 日期格式化 */
/**
 * 格式化日期
 * @param {Date|string|number} date - 日期对象、时间戳或日期字符串
 * @param {string} fmt - 格式化字符串，默认 "yyyy-MM-dd hh:mm:ss"
 * @returns {string} - 格式化后的日期字符串
 */
tool.dateFormat = function (date, fmt = 'yyyy-MM-dd hh:mm:ss') {
	if (!date) return ''
	const dateObj = new Date(date)
	if (isNaN(dateObj.getTime())) return ''

	const o = {
		'M+': dateObj.getMonth() + 1, // 月份
		'd+': dateObj.getDate(), // 日
		'h+': dateObj.getHours(), // 小时
		'm+': dateObj.getMinutes(), // 分
		's+': dateObj.getSeconds(), // 秒
		'q+': Math.floor((dateObj.getMonth() + 3) / 3), // 季度
		S: dateObj.getMilliseconds(), // 毫秒
	}
	if (/(y+)/.test(fmt)) {
		fmt = fmt.replace(RegExp.$1, (dateObj.getFullYear() + '').substr(4 - RegExp.$1.length))
	}
	for (const k in o) {
		if (new RegExp('(' + k + ')').test(fmt)) {
			fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length))
		}
	}
	return fmt
}

/* 千分符 */
/**
 * 格式化数字，添加千分位分隔符
 * @param {number|string} num - 要格式化的数字
 * @param {number} decimals - 保留小数位数，默认为0
 * @returns {string} - 格式化后的字符串
 */
tool.groupSeparator = function (num, decimals = 0) {
	if (num === null || num === undefined || num === '') return ''
	const numStr = Number(num).toFixed(decimals)
	const parts = numStr.split('.')
	parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
	return parts.join('.')
}

/* 常用加解密 */
tool.crypto = {
	//MD5加密
	MD5(data) {
		return CryptoJS.MD5(data).toString()
	},
	//BASE64加解密
	BASE64: {
		encrypt(data) {
			return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(data))
		},
		decrypt(cipher) {
			return CryptoJS.enc.Base64.parse(cipher).toString(CryptoJS.enc.Utf8)
		},
	},
	//AES加解密
	AES: {
		encrypt(data, secretKey, config = {}) {
			if (secretKey.length % 8 != 0) {
				console.warn('[SCUI error]: 秘钥长度需为8的倍数，否则解密将会失败。')
			}
			const result = CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(secretKey), {
				iv: CryptoJS.enc.Utf8.parse(config.iv || ''),
				mode: CryptoJS.mode[config.mode || 'ECB'],
				padding: CryptoJS.pad[config.padding || 'Pkcs7'],
			})
			return result.toString()
		},
		decrypt(cipher, secretKey, config = {}) {
			const result = CryptoJS.AES.decrypt(cipher, CryptoJS.enc.Utf8.parse(secretKey), {
				iv: CryptoJS.enc.Utf8.parse(config.iv || ''),
				mode: CryptoJS.mode[config.mode || 'ECB'],
				padding: CryptoJS.pad[config.padding || 'Pkcs7'],
			})
			return CryptoJS.enc.Utf8.stringify(result)
		},
	},
}

/* 树形数据转扁平数组 */
/**
 * 将树形结构转换为扁平数组
 * @param {Array} tree - 树形数组
 * @param {Object} config - 配置项 { children: "children" }
 * @returns {Array} - 扁平化后的数组
 */
tool.treeToList = function (tree, config = { children: 'children' }) {
	const result = []
	tree.forEach((item) => {
		const tmp = { ...item }
		const childrenKey = config.children || 'children'

		if (tmp[childrenKey] && tmp[childrenKey].length > 0) {
			result.push({ ...item })
			const childrenRoutes = tool.treeToList(tmp[childrenKey], config)
			result.push(...childrenRoutes)
		} else {
			result.push(tmp)
		}
	})
	return result
}

/* 获取父节点数据（保留原有函数名） */
/**
 * 根据ID获取父节点数据
 * @param {Array} list - 数据列表
 * @param {number|string} targetId - 目标ID
 * @param {Object} config - 配置项 { pid: "parent_id", idField: "id", field: [] }
 * @returns {*} - 父节点数据或指定字段
 */
tool.get_parents = function (list, targetId = 0, config = { pid: 'parent_id', idField: 'id', field: [] }) {
	let res = null
	list.forEach((item) => {
		if (item[config.idField || 'id'] === targetId) {
			if (config.field && config.field.length > 1) {
				res = {}
				config.field.forEach((field) => {
					res[field] = item[field]
				})
			} else if (config.field && config.field.length === 1) {
				res = item[config.field[0]]
			} else {
				res = item
			}
		}
	})
	return res
}

/* 获取数据字段 */
/**
 * 从数据对象中提取指定字段
 * @param {Object} data - 数据对象
 * @param {Array} fields - 字段名数组
 * @returns {*} - 提取的字段数据
 */
tool.getDataField = function (data, fields = []) {
	if (!data || typeof data !== 'object') {
		return data
	}
	if (fields.length === 0) {
		return data
	}
	if (fields.length === 1) {
		return data[fields[0]]
	} else {
		const result = {}
		fields.forEach((field) => {
			result[field] = data[field]
		})
		return result
	}
}

// 兼容旧函数名
tool.tree_to_list = tool.treeToList
tool.get_data_field = tool.getDataField

export default tool
