import config from "@/config.js"
import { sm4Encrypt, sm4Decrypt } from '@/utils/crypto';
import useUserStore from '@/stores/useUserStore';

let isRefreshing = false;
let refreshSubscribers = [];

const needToEncryptSet = new Set([
    'POST:/app/login',
    'GET:/app/user/resume',
    'POST:/app/user/resume',
    'POST:/app/user/experience/edit',
    'POST:/app/user/experience/delete',
    'GET:/app/user/experience/getSingle',
    'GET:/app/user/experience/list',
    'POST:/app/user/cert',
    'POST:/app/user/getUserArchives',
]);

const encryptPathPrefixes = [
    // '/app/common/',
	'/app/chat/',
	// '/app/speech/',
	'/app/job/',
	'/app/company/',
	'/app/companycontact/',
	'/app/appskill/',
	'/app/userworkexperiences/',
	'/app/appWxphoneSmsCode',
	'/app/sendSmsAgain',
	'/app/user/',
	'/registerUser',
	'/app/user/resume/',
	'/cms/job/recommen/',
	'/app/appLoginPhone',
	'/app/notice/',
	'/app/idCardLogin',
	'/app/phoneLogin',
];

const addRefreshSubscriber = (callback) => {
    refreshSubscribers.push(callback);
};

const notifyRefreshSubscribers = (token) => {
    refreshSubscribers.forEach((callback) => callback(token));
    refreshSubscribers = [];
};

const noEncryptSet = new Set([
    'DELETE:/app/job/applyJobCencal',
]);

export const isEncryptNeeded = (method, url) => {
    const pureUrl = url.split('?')[0];
    const key = `${method.toUpperCase()}:${pureUrl}`;
    if (noEncryptSet.has(key)) return false;
    if (needToEncryptSet.has(key)) return true;
    for (const encryptKey of needToEncryptSet) {
        const [encryptMethod, encryptUrl] = encryptKey.split(':');
        if (encryptMethod === method.toUpperCase() && pureUrl.startsWith(encryptUrl.split('/{')[0])) {
            return true;
        }
    }
    for (const prefix of encryptPathPrefixes) {
        if (pureUrl.startsWith(prefix)) {
            return true;
        }
    }
    return false;
};

export const encryptRequestData = (data) => {
    const jsonData = JSON.stringify(data);
	// const jsonData = JSON.stringify({a: '1'});
	console.log('[请求] 加密前:', jsonData)
    return {
        encrypted: true,
        encryptedData: sm4Encrypt(config.sm4Config.key, jsonData),
        timestamp: Date.now(),
    };
};

export const handleResponseData = (resData) => {
    try {
        if (resData?.encrypted) {
            const decrypted = sm4Decrypt(config.sm4Config.key, resData.encryptedData);
            resData = JSON.parse(decrypted);
            // console.log('[请求] 解密后数据:', resData);
        }
    } catch (e) {
        console.error('[请求] 解密失败:', e.message);
    }
    return resData;
};
export function request({
	url,
	method = 'GET',
	data = {},
	load = false,
	header = {}
} = {}) {

	return new Promise((resolve, reject) => {
		if (load) {
			uni.showLoading({
				title: '请稍候',
				mask: true
			});
		}
		let Authorization = ''
		if (useUserStore().token) {
			Authorization = `Bearer ${useUserStore().token}`
		}
		uni.request({
			url: config.baseUrl + url,
			method,
			data: data,
			header: {
				'Authorization': Authorization || '',
			},
			success: resData => {
				// 响应拦截
				if (resData.statusCode === 200) {
					const {
						code,
						msg
					} = resData.data
					if (code === 200) {
						resolve(resData.data)
						return
					}
					uni.showToast({
						title: msg,
						icon: 'none'
					})
				}
				if (resData.data?.code === 401 || resData.data?.code === 402) {
					useUserStore().logOut()
					uni.showToast({
						title: '登录过期，请重新登录',
						icon: 'none'
					})
					return
				}
				const err = new Error('请求出现异常，请联系工作人员')
				err.error = resData
				reject(err)
			},
			fail: err => reject(err) ,
			complete() {
				if (load) {
					uni.hideLoading();
				}
			}
		})
	})
}


/**
 * @param url  String，请求的地址，默认：none
 * @param data  Object，请求的参数，默认：{}
 * @param method  String，请求的方式，默认：GET
 * @param loading  Boolean，是否需要loading ，默认：false
 * @param header  Object，headers，默认：{}
 * @returns promise
 **/
export function createRequest(url, data = {}, method = 'GET', loading = false, headers = {},needHeader = true) {
	if (loading) {
		uni.showLoading({
			title: '请稍后',
			mask: true
		})
	}
	const header = headers || {};
	
	const doRequest = () => {
		if (needHeader) {
			header["Authorization"] = useUserStore().token ? `Bearer ${useUserStore().token}` : '';
		}
		const requestData = isEncryptNeeded(method, url) ? encryptRequestData(data) : data;
		return new Promise((resolve, reject) => {
			uni.request({
				url: config.baseUrl + url,
				method: method,
				data: requestData,
				header,
				success: resData => {
					const responseData = handleResponseData(resData.data)
					console.log('[请求] 接口地址:', config.baseUrl + url)
					console.log('[请求] 解密后数据:', JSON.stringify(responseData))
					// 响应拦截
					if (resData.statusCode === 200) {
						const {
							code,
							msg
						} = responseData
						if (code === 200) {
							resolve(responseData)
							return
						}
						// 处理业务错误
						if (responseData?.code === 401 || responseData?.code === 402) {
							handleTokenExpired(resolve, reject, doRequest, loading)
							return
						}
						// 显示具体的错误信息
						const errorMsg = msg || '请求出现异常，请联系工作人员'
						uni.showToast({
							title: errorMsg,
							icon: 'none'
						})
						const err = new Error(errorMsg)
						err.error = resData
						reject(err)
						return
					}
					// HTTP状态码不是200的情况
					const errorMsg = responseData?.msg || '网络请求失败，请检查网络连接'
					uni.showToast({
						title: errorMsg,
						icon: 'none'
					})
					const err = new Error(errorMsg)
					err.error = resData
					reject(err)
				},
				fail: (err) => {
					reject(err)
				},
				complete: () => {
					if (loading && !isRefreshing) {
						uni.hideLoading();
					}
				}
			});
		})
	}
	
	return doRequest()
}

const handleTokenExpired = (resolve, reject, retryRequest, loading) => {
    return new Promise((innerResolve, innerReject) => {
        if (isRefreshing) {
            addRefreshSubscriber((token) => {
                if (token) {
                    retryRequest().then(resolve).catch(reject).finally(innerResolve)
                } else {
                    const err = new Error('刷新token失败')
                    reject(err)
                    innerReject(err)
                }
            })
            return
        }

        isRefreshing = true

        useUserStore().refreshAccessToken().then((newToken) => {
            notifyRefreshSubscribers(newToken)
            retryRequest().then(resolve).catch(reject).finally(() => {
                isRefreshing = false
                refreshSubscribers = []
                if (loading) {
                    uni.hideLoading()
                }
                innerResolve()
            })
        }).catch((error) => {
            isRefreshing = false
            refreshSubscribers = []
            uni.showToast({
                title: '登录过期，请重新登录',
                icon: 'none'
            })
            reject(error)
            innerReject(error)
        })
    })
}


export function uploadFile(tempFilePaths, loading = false) {
	if (loading) {
		uni.showLoading({
			title: '请稍后',
			mask: true
		})
	}
	let Authorization = ''
	if (useUserStore().token) {
		Authorization = `Bearer ${useUserStore().token}`
	}

	const header = {};
	header["Authorization"] = Authorization;
	return new Promise((resolve, reject) => {
		uni.uploadFile({
			url: config.baseUrl + '/app/file/uploadFile',
			filePath: tempFilePaths,
			name: 'file',
			header,
			success: (uploadFileRes) => {
				if (uploadFileRes.statusCode === 200) {
					return resolve(uploadFileRes.data)
				}
			},
			fail: (err) => {
				reject(err)
			},
			complete: () => {
				if (loading) {
					uni.hideLoading();
				}
			}
		})
	})
}

export function myRequest(url, data = {}, method = 'GET', port = 9100, headers = {}, loading = false,urlType='') {
	let LCBaseUrl = config.LCBaseUrl
	if (port != 9100) {
		LCBaseUrl = config.LCBaseUrlInner
	}
	if(urlType=='jobRecommend'){
		LCBaseUrl=config.jobRecommendUrl
	}else if(urlType=='policyRecommend'){
		LCBaseUrl=config.policyRecommendUrl
	}
	const header = headers || {};
	// 上下文
	// /jobfair-api/jobfair/public 招聘会
	// /dashboard-api/dashboard  用户登录相关
	// /dashboard-api 获取验证码、登录
	if (loading) {
		uni.showLoading({
			title: '请稍后',
			mask: true
		})
	}
	return new Promise((resolve, reject) => {
		uni.request({
			url: LCBaseUrl + url,
			method: method,
			data: data,
			header,
			success: resData => {
				if(url=='/dashboard/auth/heart'){
					resolve(resData.data)
					return
				}else{
					// 响应拦截
					if (resData.statusCode === 200) {
						const {
							code,
							msg
						} = resData.data
						if(resData.data?.code == undefined){
							resolve(resData.data)
							return
						}
						if (code === 200) {
							resolve(resData.data)
							return
						}
						// 处理业务错误
						if (resData.data?.code === 401 || resData.data?.code === 402) {
							const pages = getCurrentPages();
							if (pages.length >= 10) {
								// 页面栈已满，使用redirectTo替代
								uni.redirectTo({
									url:'/packageB/login?flag=nw',
									fail: (err) => {
										console.error('页面跳转失败:', err);
									}
								});
							} else {
								uni.navigateTo({
									url:'/packageB/login?flag=nw',
									fail: (err) => {
										console.error('页面跳转失败:', err);
										// 失败后尝试redirectTo
										uni.redirectTo({
											url:'/packageB/login?flag=nw',
											fail: (err2) => {
												console.error('redirectTo也失败:', err2);
											}
										});
									}
								});
							}
							useUserStore().logOut()
							    
						}
						// 显示具体的错误信息
						const errorMsg = msg || '请求出现异常，请联系工作人员'
						// uni.showToast({
						// 	title: errorMsg,
						// 	icon: 'none'
						// })
						const err = new Error(errorMsg)
						err.error = resData
						reject(err)
						return
					}
					// HTTP状态码不是200的情况
					const err = new Error('网络请求失败，请检查网络连接')
					err.error = resData
					reject(err)
				}
			},
			fail: (err) => {
				reject(err)
			},
			complete: () => {
				if (loading) {
					uni.hideLoading();
				}
			}
		})
	})
}
