import { isDev, ignoreTokens, config } from "@/config";
import { locale, t } from "../locale";
import { isNull, isObject, parse, storage } from "../utils";
import { useStore } from "../store";
import { useUi } from "@/uni_modules/cool-ui";
// 请求参数类型定义
export type RequestOptions = {
	url: string; // 请求地址
	method?: RequestMethod; // 请求方法
	data?: any; // 请求体数据
	params?: any; // URL参数
	header?: any; // 请求头
	timeout?: number; // 超时时间
	withCredentials?: boolean; // 是否携带凭证
	firstIpv4?: boolean; // 是否优先使用IPv4
	enableChunked?: boolean; // 是否启用分块传输
};

// 响应数据类型定义
export type Response = {
	code: number;
	message: string;
	data: any;
};
const ui = useUi();
// 请求队列（用于等待token刷新后继续请求）
let requests: ((token: string) => void)[] = [];

// 标记token是否正在刷新
let isRefreshing = false;

// 判断当前url是否忽略token校验
const isIgnoreToken = (url: string) => {
	return ignoreTokens.some((e) => {
		const pattern = e.replace(/\*/g, ".*");
		return new RegExp(pattern).test(url);
	});
};

/**
 * 通用请求方法
 * @param options 请求参数
 * @returns Promise<T>
 */
export function request(options: RequestOptions): Promise<any | null> {
	let { url, method = "GET", data = {}, header = {}, timeout = 60000 } = options;

	const { user } = useStore();



	// 拼接基础url
	if (!url.startsWith("http")) {
		url = config.baseUrl + url;
	}
	// 开发环境下打印请求信息
	if (isDev) {
		console.log(`[${method}] ${url}`);
	}
	// 获取当前token
	let Authorization: string | null = user.token;

	// 如果是忽略token的接口，则不携带token
	if (isIgnoreToken(url)) {
		Authorization = null;
	}

	return new Promise((resolve, reject) => {
			let isRetry = false;
		// 发起请求的实际函数
		function next() {
			uni.request({
				url,
				method,
				data,
				header: {
					Authorization,
					language: locale.value,
					...(header as UTSJSONObject)
				},
				timeout,

				success(res) {
					if (isNull(res.data)) {
						res.data = {};
					}
					const { code, message, data } = parse<Response>(
						(res.data as Response)
					)!

					// 401 无权限
					if (res.statusCode == 401) {
						// 不对token接口本身做刷新，防止死循环
						if (!isRetry && url.indexOf('/oauth/token') === -1) {
							isRetry = true;
							user.refreshToken()
								.then(() => {
									Authorization = user.token;
									next();
								})
								.catch(() => {
									user.logout();
									ui.showToast({
										message: "无权限",
										type: "warn",
									})
									reject({ message: t("无权限") } as Response);
								});
							return;
						}
						// 刷新后仍然401，强制登出
						user.logout();
						ui.showToast({
							message: "无权限",
							type: "warn",
						})
						reject({ message: t("无权限") } as Response);
					}

					// 502 服务异常
					else if (res.statusCode == 502 || res.statusCode == 405) {
						ui.showToast({
							message: message || "服务异常",
							type: "warn",
						})
						reject({
							message: message || t("服务异常")
						} as Response);
					}

					// 404 未找到
					else if (res.statusCode == 404) {
						ui.showToast({
							message: `[404] ${url}`,
							type: "warn",
						})
						return reject({
							message: `[404] ${url}`
						} as Response);
					}

					// 200 正常响应
					else if (res.statusCode == 200) {
						if (res.data == null) {
							resolve(null);
						} else if (!isObject(res.data as any)) {
							resolve(res.data);
						} else {
							// 解析响应数据
							if (code == 200 || code == 0) {
								resolve(data);
							} else if (code == 1) {
								reject(res.data);
							}
							else {
								ui.showToast({
									message: message ?? t("服务异常"),
									type: "warn",
								})
								reject({ message: message } as Response);
							}
						}
					} else {
						ui.showToast({
							message: message || "服务异常",
							type: "warn",
						})
						reject({ message: message || "服务异常" } as Response);
					}
				},

				// 网络请求失败
				fail(err) {
					reject({ message: err.errMsg } as Response);
				}
			});
		};

		next();
	});
}
export function useGet(url: string, data?: any, config?: RequestOptions): Promise<any> {
	const options: RequestOptions = {
		url,
		data,
		method: 'GET',
		...config,
	}
	return request(options)
}
export function usePost(url: string, data?: any, config?: RequestOptions): Promise<any> {
	const options: RequestOptions = {
		url,
		data,
		method: 'POST',
		...config,
	}
	return request(options)
}
export function usePut(url: string, data?: any, config?: RequestOptions): Promise<any> {
	const options: RequestOptions = {
		url,
		data,
		method: 'PUT',
		...config,
	}
	return request(options)
}
export function useDelete(url: string, data?: any, config?: RequestOptions): Promise<any> {
	const options: RequestOptions = {
		url,
		data,
		method: 'DELETE',
		...config,
	}
	return request(options)
}