/**
 * 手机号脱敏：隐藏中间4位（11位手机号通用）
 * @param {string} phone - 原始手机号（可带非数字字符，如138-1234-5678）
 * @returns {string} 脱敏后手机号
 */
export function desensitizePhone(phone) {
	// 1. 提取纯数字（过滤非数字字符）
	const purePhone = (phone || "").replace(/[^\d]/g, "");

	// 2. 边界判断：非11位手机号返回原字符串（或自定义提示）
	if (purePhone.length !== 11) {
		console.warn("手机号格式不正确，需11位纯数字");
		return phone; // 或返回 ''、'手机号格式错误' 等
	}

	// 3. 脱敏：前3位 + **** + 后4位
	return purePhone.replace(/(\d{3})(\d{4})(\d{4})/, "$1****$3");
}

/**
 * 姓名合法性校验
 * @param {string} name - 待校验的姓名
 * @returns {Object} 校验结果：{ valid: boolean, msg: string }
 */
export function validateName(name) {
	// 1. 空值校验
	if (!name || name.trim() === "") {
		return {
			valid: false,
			msg: "姓名不能为空",
		};
	}
	const pureName = name.trim();

	// 2. 长度校验（2-6位，含少数民族中间点）
	if (pureName.length < 2 || pureName.length > 6) {
		return {
			valid: false,
			msg: "姓名长度应为2-6位",
		};
	}

	// 3. 正则校验：仅允许中文、少数民族中间点（·），且中间点不能在开头/结尾
	// 中文范围：[\u4e00-\u9fa5]，中间点：[\u00b7]（Unicode 标准中间点，非小数点）
	const nameReg = /^[\u4e00-\u9fa5]+([\u00b7][\u4e00-\u9fa5]+)*$/;
	if (!nameReg.test(pureName)) {
		return {
			valid: false,
			msg: "姓名仅支持中文和少数民族中间点（·），且不能包含数字、字母或特殊符号",
		};
	}

	// 4. 额外限制：中间点不能连续（如“李··四”）
	if (/[\u00b7]{2,}/.test(pureName)) {
		return {
			valid: false,
			msg: "姓名中的中间点（·）不能连续",
		};
	}

	// 校验通过
	return {
		valid: true,
		msg: "姓名格式合法",
	};
}

/**
 * 身份证号码合法性校验（支持18位/15位）
 * @param {string} idCard - 待校验的身份证号
 * @returns {Object} 校验结果：{ valid: boolean, msg: string, info?: Object }
 * info 可选返回：{ birthDate: string, gender: string }（出生日期、性别）
 */
export function validateIdCard(idCard) {
	// 1. 空值校验
	if (!idCard || idCard.trim() === "") {
		return {
			valid: false,
			msg: "身份证号码不能为空",
		};
	}
	const pureIdCard = idCard.trim().toUpperCase(); // 统一转为大写（处理X）

	// 2. 格式校验（18位或15位）
	const id18Reg =
		/^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))((0[1-9])|([12]\d)|(3[01]))\d{3}([0-9]|X)$/;
	const id15Reg =
		/^[1-9]\d{5}\d{2}((0[1-9])|(1[0-2]))((0[1-9])|([12]\d)|(3[01]))\d{3}$/;

	if (!id18Reg.test(pureIdCard) && !id15Reg.test(pureIdCard)) {
		return {
			valid: false,
			msg: "身份证号码格式错误（需18位，最后一位可含X；或15位纯数字）",
		};
	}

	// 3. 提取出生日期并校验合法性
	let birthDateStr, birthDate;
	if (pureIdCard.length === 18) {
		// 18位：第7-14位为出生日期（YYYYMMDD）
		birthDateStr = pureIdCard.slice(6, 14);
		birthDate = new Date(
			`${birthDateStr.slice(0, 4)}-${birthDateStr.slice(
        4,
        6
      )}-${birthDateStr.slice(6, 8)}`
		);
	} else {
		// 15位：第7-12位为出生日期（YYMMDD），补全为YYYYMMDD（19xx或20xx，默认19xx）
		const year = `19${pureIdCard.slice(6, 8)}`;
		const month = pureIdCard.slice(8, 10);
		const day = pureIdCard.slice(10, 12);
		birthDateStr = `${year}${month}${day}`;
		birthDate = new Date(`${year}-${month}-${day}`);
	}

	// 校验出生日期有效性（如20230230 → 日期对象会是Invalid Date）
	if (
		isNaN(birthDate.getTime()) ||
		birthDateStr.slice(0, 4) !== birthDate.getFullYear().toString() ||
		birthDateStr.slice(4, 6) !==
		(birthDate.getMonth() + 1).toString().padStart(2, "0") ||
		birthDateStr.slice(6, 8) !== birthDate.getDate().toString().padStart(2, "0")
	) {
		return {
			valid: false,
			msg: "身份证中的出生日期无效",
		};
	}

	// 4. 18位身份证额外校验：校验码合法性（加权算法）
	if (pureIdCard.length === 18) {
		// 加权因子
		const weightFactors = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
		// 校验码对应值（0-10 → 10对应X）
		const checkCodeMap = [
			"1",
			"0",
			"X",
			"9",
			"8",
			"7",
			"6",
			"5",
			"4",
			"3",
			"2",
		];
		// 计算前17位与加权因子的乘积和
		let sum = 0;
		for (let i = 0; i < 17; i++) {
			sum += parseInt(pureIdCard[i]) * weightFactors[i];
		}
		// 计算预期校验码
		const expectedCheckCode = checkCodeMap[sum % 11];
		// 对比实际校验码（最后一位）
		if (pureIdCard[17] !== expectedCheckCode) {
			return {
				valid: false,
				msg: "身份证校验码错误，可能是无效身份证",
			};
		}
	}

	// 5. 可选：提取性别（18位第17位，15位第15位；奇数=男，偶数=女）
	let gender = "";
	if (pureIdCard.length === 18) {
		const genderCode = parseInt(pureIdCard[16]);
		gender = genderCode % 2 === 1 ? "男" : "女";
	} else {
		const genderCode = parseInt(pureIdCard[14]);
		gender = genderCode % 2 === 1 ? "男" : "女";
	}

	// 校验通过，返回额外信息（出生日期、性别）
	return {
		valid: true,
		msg: "身份证号码合法",
		info: {
			birthDate: `${birthDate.getFullYear()}-${(birthDate.getMonth() + 1)
        .toString()
        .padStart(2, "0")}-${birthDate.getDate().toString().padStart(2, "0")}`,
			gender: gender,
		},
	};
}

/**
 * 过滤输入，只允许数字和最多两位小数
 * @param {string} value - 输入框当前值
 * @param {boolean} isIntegerOnly - 是否只允许正整数（无小数点），开启时最小值为1
 * @returns {string} 过滤后的合法值
 */
export function filterNumberInput(value, isIntegerOnly = false) {
	// 第一步就过滤所有非数字和非小数点的字符（包括字母）
	let filtered = value.replace(/[^\d.]/g, "");

	// 整数模式处理
	if (isIntegerOnly !== false) {
		// 移除所有小数点
		filtered = filtered.replace(/\./g, "");

		// 处理前导零
		filtered = filtered.replace(/^0+(\d)/, "$1") || filtered;

		// 空值处理（允许临时删除）
		if (filtered === "") {
			return "";
		}

		// 最小值限制
		if (filtered === isIntegerOnly || parseInt(filtered, 10) < isIntegerOnly) {
			return isIntegerOnly;
		}

		return filtered;
	}

	// 小数模式处理
	const parts = filtered.split(".");
	if (parts.length > 1) {
		filtered = parts[0] + "." + (parts[1].substring(0, 2) || "");
	}

	// 处理前导零
	if (
		filtered.startsWith("0") &&
		filtered.length > 1 &&
		!filtered.startsWith("0.")
	) {
		filtered = filtered.replace(/^0+(\d)/, "$1");
	}

	return filtered;
}

/**
 * uni-app 跨平台权限判断通用方法
 * @param {String} permissionType - 权限类型（通用名称，如 'camera'、'location' 等）
 * @returns {Promise<{granted: Boolean, status: String, platform: String}>} - 权限状态结果
 *   - granted: 是否已授权（Boolean）
 *   - status: 详细状态（'granted'|'denied'|'undetermined'|'limited'）
 *   - platform: 当前平台
 */
export function checkPermission(permissionType) {
	return new Promise((resolve, reject) => {
		// 获取当前平台信息
		const systemInfo = uni.getSystemInfoSync();
		const platform = systemInfo.platform; // 'android'|'ios'|'devtools'（小程序模拟器）
		const env = process.env.NODE_ENV; // 环境变量（用于区分小程序/H5/App）

		// 权限类型映射表：将通用权限名称映射到各平台具体权限名
		const permissionMap = {
			// 通用权限名称: { 平台: 平台权限名 }
			camera: {
				weixin: "scope.camera", // 微信小程序
				alipay: "scope.camera", // 支付宝小程序
				android: "android.permission.CAMERA", // App-Android
				ios: "camera", // App-iOS（简化处理，实际需调用原生 API）
				h5: "camera", // H5 浏览器权限
			},
			location: {
				weixin: "scope.userLocation",
				alipay: "scope.userLocation",
				android: "android.permission.ACCESS_FINE_LOCATION",
				ios: "location",
				h5: "geolocation",
			},
			microphone: {
				weixin: "scope.record",
				alipay: "scope.record",
				android: "android.permission.RECORD_AUDIO",
				ios: "microphone",
				h5: "microphone",
			},
			album: {
				weixin: "scope.writePhotosAlbum",
				alipay: "scope.album",
				android: "android.permission.WRITE_EXTERNAL_STORAGE",
				ios: "photoLibrary",
				h5: "clipboard-write", // H5 相册权限支持有限
			},
			// 可根据需求扩展更多权限类型
		};

		// 获取当前平台对应的权限名
		const getPlatformPermission = () => {
			if (typeof wx !== "undefined" && wx.getSetting)
				return permissionMap[permissionType]?.weixin; // 微信小程序
			if (typeof my !== "undefined" && my.getSetting)
				return permissionMap[permissionType]?.alipay; // 支付宝小程序
			if (platform === "android") return permissionMap[permissionType]?.android; // App-Android
			if (platform === "ios") return permissionMap[permissionType]?.ios; // App-iOS
			return permissionMap[permissionType]?.h5; // H5
		};

		const platformPermission = getPlatformPermission();
		if (!platformPermission) {
			return reject(new Error(`不支持的权限类型: ${permissionType}`));
		}

		// ----------------- 分平台处理 -----------------
		// 1. 微信/支付宝小程序
		if (typeof wx !== "undefined" && wx.getSetting) {
			uni.getSetting({
				success: (res) => {
					const authSetting = res.authSetting || {};
					const isGranted = authSetting[platformPermission] === true;
					const status = isGranted ?
						"granted" :
						authSetting[platformPermission] === false ?
						"denied" :
						"undetermined";
					resolve({
						granted: isGranted,
						status,
						platform: "weixin"
					});
				},
				fail: (err) => reject(err),
			});
		}
		// 2. App-Android 平台
		else if (platform === "android" && typeof plus !== "undefined") {
			try {
				const Context = plus.android.importClass("android.content.Context");
				const Activity = plus.android.runtimeMainActivity();
				const PackageManager = plus.android.importClass(
					"android.content.pm.PackageManager"
				);

				// 检查权限状态
				const granted =
					Activity.checkSelfPermission(platformPermission) ===
					PackageManager.PERMISSION_GRANTED;
				resolve({
					granted,
					status: granted ? "granted" : "denied",
					platform: "android",
				});
			} catch (err) {
				reject(err);
			}
		}
		// 3. App-iOS 平台
		else if (platform === "ios" && typeof plus !== "undefined") {
			try {
				// iOS 权限需通过原生 API 检查（以相机为例，其他权限类似）
				const result = {
					granted: false,
					status: "denied",
					platform: "ios"
				};

				if (permissionType === "camera") {
					// 相机权限检查（iOS 需调用 AVCaptureDevice）
					const AVCaptureDevice = plus.ios.importClass("AVCaptureDevice");
					const authStatus =
						AVCaptureDevice.authorizationStatusForMediaType("vide");
					// AVCaptureDeviceAuthorizationStatus 枚举值：
					// 0: notDetermined（未请求）, 1: restricted（受限制）, 2: denied（拒绝）, 3: authorized（授权）
					result.granted = authStatus === 3;
					result.status =
						authStatus === 3 ?
						"granted" :
						authStatus === 0 ?
						"undetermined" :
						"denied";
				}
				// 可扩展其他 iOS 权限（如定位、麦克风等）
				else if (permissionType === "location") {
					const CLLocationManager = plus.ios.importClass("CLLocationManager");
					const authStatus = CLLocationManager.authorizationStatus();
					// CLAuthorizationStatus 枚举值：
					// 0: notDetermined, 1: restricted, 2: denied, 3: authorizedAlways, 4: authorizedWhenInUse
					result.granted = authStatus === 3 || authStatus === 4;
					result.status = result.granted ?
						"granted" :
						authStatus === 0 ?
						"undetermined" :
						"denied";
				}

				resolve(result);
			} catch (err) {
				reject(err);
			}
		}
		// 4. H5 平台（浏览器权限）
		else if (typeof navigator !== "undefined" && navigator.permissions) {
			navigator.permissions
				.query({
					name: platformPermission
				})
				.then((permissionStatus) => {
					resolve({
						granted: permissionStatus.state === "granted",
						status: permissionStatus.state, // 'granted'|'denied'|'prompt'
						platform: "h5",
					});
				})
				.catch((err) => reject(err));
		}
		// 5. 其他平台（如百度小程序、字节跳动小程序等，可扩展）
		else {
			reject(new Error(`当前平台不支持权限判断: ${platform}`));
		}
	});
}

/**
 * 判断字符串是否为合法的 JSON 数组
 * @param {string} str - 待判断的字符串
 * @returns {boolean} true=是JSON数组字符串 / false=普通字符串/其他
 */
export function isJsonArrayString(str) {
	// 1. 非字符串直接返回 false
	if (typeof str !== 'string') {
		return false;
	}

	// 2. 空字符串返回 false（根据业务可调整）
	if (str.trim() === '') {
		return false;
	}

	try {
		// 3. 尝试解析 JSON
		const parsed = JSON.parse(str);
		// 4. 校验解析结果是否为数组
		return Array.isArray(parsed);
	} catch (e) {
		// 解析失败（普通字符串/非法 JSON）→ 返回 false
		return false;
	}
}

/**
 * 判断目标值是否包含指定字符串
 * @param {string|number|array} target - 目标值（字符串/数字/数组）
 * @param {string} searchStr - 要查找的子字符串
 * @param {object} [options] - 可选配置
 * @param {boolean} [options.ignoreCase=false] - 是否忽略大小写
 * @param {boolean} [options.allowEmpty=false] - 当 searchStr 为空时，是否返回 true（默认 false）
 * @returns {boolean} 是否包含指定字符串
 */
export function includesString(target, searchStr, options = {}) {
	// 解构配置，设置默认值
	const {
		ignoreCase = false, allowEmpty = false
	} = options;

	// 1. 处理 searchStr 为空的情况
	if (searchStr === '' || searchStr === null || searchStr === undefined) {
		return allowEmpty;
	}

	// 2. 统一将目标值转为字符串（兼容数字/数组等）
	let targetStr = '';
	if (typeof target === 'string') {
		targetStr = target;
	} else if (typeof target === 'number') {
		targetStr = String(target);
	} else if (Array.isArray(target)) {
		// 数组：拼接为字符串（也可改为 "数组中某一项包含"，根据需求调整）
		targetStr = target.join(',');
	} else {
		// 其他类型（对象/布尔等）：转为字符串或返回 false
		targetStr = String(target);
	}

	// 3. 处理大小写忽略
	const processedTarget = ignoreCase ? targetStr.toLowerCase() : targetStr;
	const processedSearch = ignoreCase ? searchStr.toLowerCase() : searchStr;

	// 4. 执行包含判断
	return processedTarget.includes(processedSearch);
}

/**
 * 校验一维基础类型数组A的元素是否存在于数组B（支持部分/全部存在，默认全部存在）
 * @param {Array<string|number|boolean>} arrA - 待校验的一维数组
 * @param {Array<string|number|boolean>} arrB - 参考的一维数组
 * @param {boolean} [partial=false] - 是否校验「部分存在」（true=部分存在，false=全部存在，默认false）
 * @returns {boolean} 校验结果
 */
export function checkArrayElementsExist(arrA, arrB, partial = false) {
	// 边界处理：空数组特殊逻辑
	if (arrA.length === 0) return !partial

	// 转Set优化查找性能（一维数组核心优化）
	const bSet = new Set(arrB)

	// 核心逻辑：partial=true → some（部分存在），partial=false → every（全部存在）
	return partial ?
		arrA.some(item => bSet.has(item)) :
		arrA.every(item => bSet.has(item))
}