// HTTP请求配置和拦截器
// 基于uView-next的luch-request库实现

import { HTTP_CONFIG, checkApiAuth } from './config.js'

/**
 * 初始化HTTP配置
 * @param {Object} vm Vue实例，用于访问vuex等全局状态
 */
export default (vm) => {
	// 初始化请求配置
	uni.$u.http.setConfig((config) => {
		config.baseURL = HTTP_CONFIG.baseURL
		config.timeout = HTTP_CONFIG.timeout
		config.header = {
			'Content-Type': 'application/json;charset=UTF-8'
		}
		return config
	})

	// 请求拦截器
	uni.$u.http.interceptors.request.use((config) => {
		// 初始化请求拦截器时，会执行此方法，此时data为undefined，赋予默认{}
		config.data = config.data || {}
		config.custom = config.custom || {}

		// 自动检查接口是否需要鉴权（如果没有明确指定）
		if (config.custom.auth === undefined) {
			config.custom.auth = checkApiAuth(config.url)
		}

		// 根据custom参数中配置的是否需要token，添加对应的请求头
		if (config.custom.auth) {
			// 从本地存储获取token
			const token = uni.getStorageSync(HTTP_CONFIG.storageKeys.token)
			if (token) {
				config.header.Authorization = `Bearer ${token}`
			} else {
				// 如果需要token但没有token，可以跳转到登录页
				console.warn('需要token但未找到，请先登录')
			}
		}

		// 根据custom参数配置是否显示loading
		if (config.custom.loading !== false) {
			uni.showLoading({
				title: config.custom.loadingText || '请稍候...',
				mask: true
			})
		}

		return config
	}, config => {
		// 请求错误处理
		return Promise.reject(config)
	})

	// 响应拦截器
	uni.$u.http.interceptors.response.use((response) => {
		/* 对响应成功做点什么 可使用async await 做异步操作*/

		// 隐藏loading
		uni.hideLoading()

		const data = response.data
		const custom = response.config?.custom

		// 统一的响应数据处理
		if (data.code !== undefined) {
			// 如果服务端返回的状态码不等于200，则reject()
			if (data.code !== 200) {
				// 如果没有显式定义custom的toast参数为false的话，默认对报错进行toast弹出提示
				if (custom?.toast !== false) {
					uni.$u.toast(data.message || '请求失败')
				}

				// 特殊状态码处理
				if (data.code === 401) {
					// token过期，清除本地token并跳转到登录页
					uni.removeStorageSync(HTTP_CONFIG.storageKeys.token)
					uni.removeStorageSync(HTTP_CONFIG.storageKeys.refreshToken)
					uni.removeStorageSync(HTTP_CONFIG.storageKeys.userInfo)
					uni.reLaunch({
						url: HTTP_CONFIG.loginPage
					})
					return Promise.reject(data)
				}

				// 如果需要catch返回，则进行reject
				if (custom?.catch) {
					return Promise.reject(data)
				} else {
					// 否则返回一个pending中的promise，请求不会进入catch中
					return new Promise(() => {})
				}
			}
		}

		// 返回处理后的数据
		return data.data !== undefined ? data.data : data
	}, (response) => {
		/* 对响应错误做点什么 （statusCode !== 200）*/

		// 隐藏loading
		uni.hideLoading()

		const custom = response.config?.custom

		// 网络错误处理
		let errorMessage = '网络错误，请检查网络连接'

		if (response.statusCode) {
			switch (response.statusCode) {
				case 400:
					errorMessage = '请求参数错误'
					break
				case 401:
					errorMessage = '未授权，请重新登录'
					// 清除本地认证信息
					uni.removeStorageSync(HTTP_CONFIG.storageKeys.token)
					uni.removeStorageSync(HTTP_CONFIG.storageKeys.refreshToken)
					uni.removeStorageSync(HTTP_CONFIG.storageKeys.userInfo)
					// 跳转到登录页
					uni.reLaunch({
						url: HTTP_CONFIG.loginPage
					})
					break
				case 403:
					errorMessage = '拒绝访问'
					break
				case 404:
					errorMessage = '请求地址不存在'
					break
				case 500:
					errorMessage = '服务器内部错误'
					break
				case 502:
					errorMessage = '网关错误'
					break
				case 503:
					errorMessage = '服务不可用'
					break
				case 504:
					errorMessage = '网关超时'
					break
				default:
					errorMessage = `连接错误${response.statusCode}`
			}
		}

		// 显示错误提示
		if (custom?.toast !== false) {
			uni.$u.toast(errorMessage)
		}

		console.error('请求错误：', response)
		return Promise.reject(response)
	})
}
