// 公共方法工具类

/**
 * 日期处理相关方法
 */
export const dateUtil = {
	/**
	 * 安全解析日期，兼容 iOS
	 * @param {Date|string|number} date 
	 * @returns {Date}
	 */
	parseSafe(date) {
		if (!date) return new Date();
		if (date instanceof Date) return date;
		if (typeof date === 'string') {
			// 兼容 iOS 的 YYYY-MM-DD 解析，并处理可能的空格/T问题
			const normalizedDate = date.replace(/-/g, '/');
			return new Date(normalizedDate);
		}
		return new Date(date);
	},

	/**
	 * 格式化日期
	 * @param {Date|string|number} date - 日期对象或时间戳
	 * @param {string} format - 格式化字符串，默认为 'YYYY-MM-DD HH:mm:ss'
	 * @returns {string} 格式化后的日期字符串
	 */
	format(date, format = 'YYYY-MM-DD HH:mm:ss') {
		if (!date) return '';

		date = this.parseSafe(date);

		const year = date.getFullYear();
		const month = String(date.getMonth() + 1).padStart(2, '0');
		const day = String(date.getDate()).padStart(2, '0');
		const hours = String(date.getHours()).padStart(2, '0');
		const minutes = String(date.getMinutes()).padStart(2, '0');
		const seconds = String(date.getSeconds()).padStart(2, '0');

		return format
			.replace('YYYY', year)
			.replace('MM', month)
			.replace('DD', day)
			.replace('HH', hours)
			.replace('mm', minutes)
			.replace('ss', seconds);
	},

	/**
	 * 获取当前日期
	 * @param {string} format - 格式化字符串
	 * @returns {string} 当前日期字符串
	 */
	now(format = 'YYYY-MM-DD HH:mm:ss') {
		return this.format(new Date(), format);
	},

	/**
	 * 获取相对时间
	 * @param {Date|string|number} date - 日期对象或时间戳
	 * @returns {string} 相对时间描述
	 */
	relative(date) {
		if (!date) return '';

		date = this.parseSafe(date);

		const now = new Date();
		const diff = now - date;
		const seconds = Math.floor(diff / 1000);
		const minutes = Math.floor(seconds / 60);
		const hours = Math.floor(minutes / 60);
		const days = Math.floor(hours / 24);

		if (seconds < 60) return '刚刚';
		if (minutes < 60) return `${minutes}分钟前`;
		if (hours < 24) return `${hours}小时前`;
		if (days < 30) return `${days}天前`;

		return this.format(date, 'YYYY-MM-DD');
	},

	/**
	 * 智能时间格式化
	 * 今天 HH:mm
	 * 昨天 HH:mm
	 * 其他 MM-DD HH:mm
	 * @param {Date|string|number} date - 日期对象或时间戳
	 * @returns {string} 格式化后的时间字符串
	 */
	smart(date) {
		if (!date) return '';

		date = this.parseSafe(date);

		const now = new Date();
		const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
		const yesterday = new Date(today);
		yesterday.setDate(yesterday.getDate() - 1);

		const target = new Date(date.getFullYear(), date.getMonth(), date.getDate());

		const hours = String(date.getHours()).padStart(2, '0');
		const minutes = String(date.getMinutes()).padStart(2, '0');
		const timeStr = `${hours}:${minutes}`;

		if (target.getTime() === today.getTime()) {
			return `今天 ${timeStr}`;
		} else if (target.getTime() === yesterday.getTime()) {
			return `昨天 ${timeStr}`;
		} else {
			const month = String(date.getMonth() + 1).padStart(2, '0');
			const day = String(date.getDate()).padStart(2, '0');
			return `${month}-${day} ${timeStr}`;
		}
	},

	/**
	 * 仿支付宝消息列表时间格式化
	 * 今天: 原样不显示 (或者按需可显示 HH:mm) 但根据你的图示只有 昨天/星期/日期
	 * 昨天: 返回 "昨天"
	 * 近一周内且不是今天昨天: 返回 "星期X"
	 * 超过一周: 按照 format 返回 (或根据 hideCurrentYear 决定当年是否隐藏年份)
	 * @param {Date|string|number} date - 日期对象或时间戳
	 * @param {boolean} hideCurrentYear - 是否在当年隐藏年份，默认为 true
	 * @param {string} format - 自定义日期格式，默认为 'YYYY/M/D' (支持 YYYY, MM, M, DD, D 等)
	 * @returns {string} 格式化后的时间字符串
	 */
	formatMessageTime(date, hideCurrentYear = false, format = 'YYYY/M/D') {
		if (!date) return '';

		date = this.parseSafe(date);

		const now = new Date();
		// 将时分秒抹零，只取日期部分进行比对
		const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
		const targetDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());

		const diffDays = Math.floor((today.getTime() - targetDate.getTime()) / (1000 * 60 * 60 * 24));

		if (diffDays === 0) {
			// 如果需要显示今天的具体时间可返回： `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`
			return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
		} else if (diffDays === 1) {
			return '昨天';
		} else if (diffDays > 1 && diffDays < 7) {
			const weekDays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
			return weekDays[date.getDay()];
		} else {
			// 超过7天
			let resultFormat = format;
			if (hideCurrentYear && targetDate.getFullYear() === now.getFullYear()) {
				// 智能去除年份及紧跟的连接符、汉字或变宽空格（例如: "YYYY-", "YYYY/", "YYYY年"）
				resultFormat = resultFormat.replace(/YYYY[-/年\s]*/g, '');
			}

			const year = date.getFullYear();
			const month = date.getMonth() + 1;
			const day = date.getDate();

			return resultFormat
				.replace(/YYYY/g, year)
				.replace(/MM/g, String(month).padStart(2, '0'))
				.replace(/M/g, month)
				.replace(/DD/g, String(day).padStart(2, '0'))
				.replace(/D/g, day);
		}
	}
};

/**
 * 数字处理相关方法
 */
export const numberUtil = {
	/**
	 * 格式化数字，添加千分位
	 * @param {number|string} num - 数字或数字字符串
	 * @returns {string} 格式化后的数字字符串
	 */
	format(num) {
		if (num === null || num === undefined) return '0';

		const number = typeof num === 'string' ? parseFloat(num) : num;
		if (isNaN(number)) return '0';

		return number.toLocaleString();
	},

	/**
	 * 格式化金额
	 * @param {number|string} amount - 金额
	 * @param {number} decimals - 小数位数，默认为2
	 * @returns {string} 格式化后的金额字符串
	 */
	formatMoney(amount, decimals = 2) {
		if (amount === null || amount === undefined) return '0.00';

		const number = typeof amount === 'string' ? parseFloat(amount) : amount;
		if (isNaN(number)) return '0.00';

		return number.toFixed(decimals);
	},

	/**
	 * 格式化金额，添加千分位并保留两位小数
	 * @param {number|string} val - 金额
	 * @returns {string} 格式化后的金额字符串
	 */
	formatMoneyWithThousand(val) {
		let num = Number(val);
		if (isNaN(num)) {
			return '0.00';
		}
		let str = num.toFixed(2);
		let parts = str.split('.');
		parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
		return parts.join('.');
	},

	/**
	 * 随机数生成
	 * @param {number} min - 最小值
	 * @param {number} max - 最大值
	 * @returns {number} 随机数
	 */
	random(min, max) {
		return Math.floor(Math.random() * (max - min + 1)) + min;
	},

	/**
	 * 保留小数位
	 * @param {number} num - 数字
	 * @param {number} decimals - 小数位数，默认为2
	 * @returns {string} 保留小数位后的数字字符串
	 */
	toFiexd(num, decimals = 2) {
		return Number(num).toFixed(decimals);
	}
};

/**
 * 字符串处理相关方法
 */
export const stringUtil = {
	/**
	 * 截断字符串
	 * @param {string} str - 原始字符串
	 * @param {number} length - 截断长度
	 * @param {string} suffix - 后缀，默认为 '...'
	 * @returns {string} 截断后的字符串
	 */
	truncate(str, length, suffix = '...') {
		if (!str || str.length <= length) return str;

		return str.substring(0, length) + suffix;
	},

	/**
	 * 生成唯一ID
	 * @returns {string} 唯一ID
	 */
	uuid() {
		return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
			const r = Math.random() * 16 | 0;
			const v = c === 'x' ? r : (r & 0x3 | 0x8);
			return v.toString(16);
		});
	},

	/**
	 * 手机号脱敏
	 * @param {string} phone - 手机号
	 * @returns {string} 脱敏后的手机号
	 */
	maskPhone(phone) {
		if (!phone || phone.length !== 11) return phone;

		return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
	},

	/**
	 * 身份证号脱敏
	 * @param {string} idCard - 身份证号
	 * @returns {string} 脱敏后的身份证号
	 */
	maskIdCard(idCard) {
		if (!idCard) return idCard;

		const length = idCard.length;
		if (length < 8) return idCard;

		return idCard.substring(0, 4) + '*'.repeat(length - 8) + idCard.substring(length - 4);
	},

	/**
	 * 护照号脱敏
	 * @param {string} passport - 护照号
	 * @returns {string} 脱敏后的护照号
	 */
	maskPassport(passport) {
		if (!passport) return passport;

		const length = passport.length;
		if (length <= 4) return passport;

		return passport.substring(0, 2) + '*'.repeat(length - 4) + passport.substring(length - 2);
	}
};

/**
 * 设备信息相关方法
 */
export const deviceUtil = {
	/**
	 * 获取系统信息
	 * @returns {Promise<Object>} 系统信息对象
	 */
	getSystemInfo() {
		return new Promise((resolve, reject) => {
			uni.getSystemInfo({
				success: resolve,
				fail: reject
			});
		});
	},

	/**
	 * 获取状态栏高度
	 * @returns {Promise<number>} 状态栏高度
	 */
	async getStatusBarHeight() {
		try {
			const systemInfo = await this.getSystemInfo();
			return systemInfo.statusBarHeight || 0;
		} catch (error) {
			console.error('获取状态栏高度失败:', error);
			return 0;
		}
	},

	/**
	 * 判断是否为iOS设备
	 * @returns {Promise<boolean>} 是否为iOS设备
	 */
	async isIOS() {
		try {
			const systemInfo = await this.getSystemInfo();
			return systemInfo.platform === 'ios';
		} catch (error) {
			console.error('获取设备平台失败:', error);
			return false;
		}
	},

	/**
	 * 判断是否为Android设备
	 * @returns {Promise<boolean>} 是否为Android设备
	 */
	async isAndroid() {
		try {
			const systemInfo = await this.getSystemInfo();
			return systemInfo.platform === 'android';
		} catch (error) {
			console.error('获取设备平台失败:', error);
			return false;
		}
	},

	/**
	 * 获取窗口宽度
	 * @returns {Promise<number>} 窗口宽度（px）
	 */
	async getWindowWidth() {
		try {
			const systemInfo = await this.getSystemInfo();
			return systemInfo.windowWidth || 0;
		} catch (error) {
			console.error('获取窗口宽度失败:', error);
			return 0;
		}
	},

	/**
	 * 获取窗口高度
	 * @returns {Promise<number>} 窗口高度（px）
	 */
	async getWindowHeight() {
		try {
			const systemInfo = await this.getSystemInfo();
			return systemInfo.windowHeight || 0;
		} catch (error) {
			console.error('获取窗口高度失败:', error);
			return 0;
		}
	}
};


/**
 * UI相关方法
 */
export const uiUtil = {
	/**
	 * 显示加载提示
	 * @param {string} title - 提示文本
	 * @param {boolean} mask - 是否显示遮罩
	 * @returns {void}
	 */
	showLoading(title = '加载中', mask = true) {
		uni.showLoading({
			title,
			mask
		});
	},

	/**
	 * 隐藏加载提示
	 * @returns {void}
	 */
	hideLoading() {
		uni.hideLoading();
	},

	/**
	 * 显示错误提示
	 * @param {string} title - 提示文本
	 * @param {number} duration - 显示时长
	 * @returns {void}
	 */
	showError(title, duration = 1500) {
		uni.showToast({
			title,
			icon: 'none',
			duration
		});
	},

	/**
	 * 显示警告提示
	 * @param {string} title - 提示文本
	 * @param {string} content - 提示内容
	 * @param {Function} confirm - 确认回调
	 * @param {Function} cancel - 取消回调
	 * @returns {void}
	 */
	showConfirm(title, content, confirm, cancel) {
		uni.showModal({
			title,
			content,
			success(res) {
				if (res.confirm) {
					confirm && confirm();
				} else if (res.cancel) {
					cancel && cancel();
				}
			}
		});
	}
};

/**
 * 其他工具方法
 */
export const util = {
	/**
	 * 设置底部状态栏颜色
	 * @param {string} backgroundColor - 颜色值
	 * @returns {void}
	 */
	setAndroidSystemBarColor(backgroundColor) {
		// 使用同步方式判断或直接通过编译宏/plus判断
		const isAndroid = uni.getSystemInfoSync().platform === 'android';
		if (isAndroid) {
			try {
				// #ifdef APP-PLUS&&!APP-HARMONY
				if (plus.os.name === 'Android') {
					let color = plus.android.newObject("android.graphics.Color");
					let activity = plus.android.runtimeMainActivity();
					let colorInt = plus.android.invoke(color, "parseColor", backgroundColor);
					let window = plus.android.invoke(activity, "getWindow");
					plus.android.invoke(window, "setNavigationBarColor", colorInt);
					uni.setNavigationBarColor({
						animation: { // 动画效果
							duration: 100,
							timingFunc: 'easeIn'
						}
					})
					setTimeout(function () {
						uni.setNavigationBarColor({
							animation: { // 动画效果
								duration: 100,
								timingFunc: 'easeIn'
							}
						})
					}, 200);
				}
				// #endif
			} catch (err) {
				console.log("状态栏修改失败", err);
				uni.setNavigationBarColor({
					animation: { // 动画效果
						duration: 100,
						timingFunc: 'easeIn'
					}
				})
			}
		}
	},

	/**
	 * 点击标题栏按钮
	 * @param {*} button 
	 */
	clickTitlePopupButton(button) {
		button.click()
	},

	/**
	 * 页面跳转
	 * @param {*} url 
	 */
	goPage(url) {
		uni.navigateTo({
			url
		});
	},


	/**
	 * 返回
	 */
	goBack() {
		uni.navigateBack();
	}
};

/**
 * 生成随机数据工具
 */
export const randomUtil = {
	/**
	 * 生成随机数
	 * @param {number} min - 最小值
	 * @param {number} max - 最大值
	 * @returns {number} 随机数
	 */
	random(min, max) {
		return Math.floor(Math.random() * (max - min + 1)) + min;
	},

	/**
	 * 生成随机时间格式化时间
	 * @param {string|number|Date} startTime - 开始时间
	 * @param {string|number|Date} endTime - 结束时间
	 * @param {string} format - 格式化字符串
	 * @returns {string} 格式化后的时间
	 */
	randomTime(startTime, endTime, format = 'YYYY-MM-DD HH:mm:ss') {
		let end;
		if (endTime) {
			end = dateUtil.parseSafe(endTime).getTime();
		} else {
			end = Date.now();
		}

		let start;
		if (startTime) {
			start = dateUtil.parseSafe(startTime).getTime();
		} else {
			// 默认为结束时间往前推3个月
			const date = new Date(end);
			date.setMonth(date.getMonth() - 3);
			start = date.getTime();
		}

		const randomTimestamp = Math.floor(Math.random() * (end - start + 1)) + start;
		return dateUtil.format(randomTimestamp, format);
	},

	/**
	 * 生成随机金额
	 * @param {number} min - 最小值
	 * @param {number} max - 最大值
	 * @returns {string} 随机金额
	 */
	randomMoney(min = 0, max = 5000) {
		const num = Math.random() * (max - min) + min;
		return num.toFixed(2);
	},

	/**
	 * 随机生成指定位数订单号
	 * @param {number} length - 订单号位数
	 * @returns {string} 订单号
	 */
	randomOrderNumber(length = 16) {
		if (length < 13) {
			// 长度小于13，直接返回随机数字字符串
			let result = '';
			for (let i = 0; i < length; i++) {
				result += Math.floor(Math.random() * 10);
			}
			return result;
		}

		// 长度大于等于13，使用时间戳+随机数
		const timestamp = Date.now().toString();
		let result = timestamp;
		const padding = length - timestamp.length;

		if (padding > 0) {
			for (let i = 0; i < padding; i++) {
				result += Math.floor(Math.random() * 10);
			}
		}

		return result;
	}
};

export const imgLocal = {
	simpleHash(str) {
		let hash = 0;
		for (let i = 0; i < str.length; i++) {
			hash = (hash << 5) - hash + str.charCodeAt(i);
			hash |= 0;
		}
		return Math.abs(hash).toString(36);
	},
	getLocalImage(url) {
		return new Promise((resolve, reject) => {
			if (!url) return reject('url不能为空');

			const CACHE_KEY = 'IMG_CACHE_MAP';
			const cache = uni.getStorageSync(CACHE_KEY) || {};

			// 🔥 1. 用简单 hash 作为 key（避免超长 URL）
			const key = this.simpleHash(url);

			// 2. 命中缓存
			if (cache[key]) {
				let resultPath = cache[key];
				// #ifdef APP-PLUS&&!APP-HARMONY
				// iOS/Android 编译刷新后沙盒绝对路径的 UUID 会变！必须用相对路径重新计算最新绝对路径
				resultPath = plus.io.convertLocalFileSystemURL(`_doc/img_cache/${key}.jpg`);
				// #endif
				return resolve(resultPath);
			}
			const config = uni.getStorageSync('config')
			let imgConfig = config?.config?.['client.uniapp.img_path']?.alipay || 'http://cdn.u8t.cn/flaunt/uni_mp/img/alipay/static/image/'
			url = imgConfig + url
			// #ifdef APP-PLUS&&!APP-HARMONY
			const filename = `_doc/img_cache/${key}.jpg`;

			const task = plus.downloader.createDownload(
				url, {
				filename
			},
				(download, status) => {
					if (status === 200) {
						const localPath = plus.io.convertLocalFileSystemURL(download.filename);

						cache[key] = localPath; // 虽然存了绝对路径，但上面命中缓存时会强制重新计算
						uni.setStorageSync(CACHE_KEY, cache);

						resolve(localPath);
					} else {
						reject('下载失败：' + status);
					}
				}
			);

			task.start();
			// #else
			uni.downloadFile({
				url,
				success: (res) => {
					if (res.statusCode === 200) {
						resolve(res.tempFilePath);
					} else {
						reject('失败');
					}
				},
				fail: reject
			});
			// #endif
		});
	}
}


// 默认导出所有工具方法
export default {
	...dateUtil,
	...numberUtil,
	...stringUtil,
	...deviceUtil,
	...uiUtil,
	...util,
	...randomUtil,
	...imgLocal
};