// ajax.js

// 引入 uni-ajax 模块
import ajax from 'uni-ajax'
import store from '@/store'

// 错误log上传
function errorApiLogUpload(response) {
	const code = response?.data?.code || ''
	const isLog = response?.config?.header?.isLog // 上报问题接口
	if (!isLog && code && code !== 200) {
		const url = response?.config?.url
		console.log('errorApiLogUpload', url, code, response)
		const content = '【前端接口日志】：' + JSON.stringify(response)
		instance.post('/shunt/proposal-apply', {
			content
		}, {
			header: {
				// 避免死循环
				isLog: 1,
				// 上传log 专属token
				token: 'eyJhbGciOiJIUzUxMiJ9.eyJ5ZWFySWQiOiIyMDIyIiwiY29sbGVnZUlkIjotMSwic3R1ZGVudE5vIjoiLTEiLCJpc3N1ZXIiOiJzaHVudCBhdXRoIEpXVCBJc3N1ZXIgMS4wIiwiZXhwIjozNzY1NDEzMDU3Mn0.9OkmMbwt7tFRdgOopNVPYCq0VNXE-f-Y-yv57kfRZQDjDy_THGvsu_UQyOyGkgV9d8WoPklagBB5K2Bbj5OFdA'
			}
		})
	}
}
// 创建请求实例
const instance = ajax.create({
	// 初始配置
	baseURL: '',
	timeout: 6000,
	// responseType: 'json',
	// withCredentials: true
})
/* 无感刷新 Token */
let isRefreshing = false // 当前是否在请求刷新 Token
let requestQueue = [] // 将在请求刷新 Token 中的请求暂存起来，等刷新 Token 后再重新请求

// 执行暂存起来的请求
const executeQueue = error => {
	requestQueue.forEach(promise => {
		if (error) {
			promise.reject(error)
		} else {
			promise.resolve()
		}
	})

	requestQueue = []
}

// 刷新 Token 请求
const refreshToken = () => instance.post('/shunt/login', {
	code: uni.getStorageSync('code')
})
// 刷新 Token 请求处理，参数为刷新成功后的回调函数
const refreshTokenHandler = afresh => {
	// 如果当前是在请求刷新 Token 中，则将期间的请求暂存起来
	if (isRefreshing) {
		return new Promise((resolve, reject) => {
			requestQueue.push({
				resolve,
				reject
			})
		}).then(afresh)
	}

	isRefreshing = true

	return new Promise((resolve, reject) => {
		uni.showLoading({
			title: '登录中',
			mask: true
		})
		let token = ''
		store.commit('user/setToken', token)
		refreshToken()
			.then(res => {
				errorApiLogUpload(res)
				token = res?.data?.token || ''
				// if (token) {
				// 	uni.setStorageSync('TOKEN', token)
				// 	resolve(afresh?.())
				// 	executeQueue(null)
				// } else {
				// 	return Promise.reject(res)
				// }
			})
			.catch(err => {
				// uni.removeStorageSync('TOKEN')
				// reject(err)
				// executeQueue(err)
				console.error('login', error)
			})
			.finally(() => {
				isRefreshing = false
				uni.hideLoading()

				store.commit('user/setToken', token)
				if (token) {
					store.dispatch('user/updateUserInfo')
					// 重新获取接口的话 旧的接口会保留问题token，导致登录死循环
					// setTimeout(() => {
					// 	resolve(afresh?.())
					// 	executeQueue(null)
					// }, 5000)
					uni.reLaunch({
						url: '/pages/index/index'
					});
				} else {
					store.commit('user/logout', '')
					uni.reLaunch({
						url: '/pages/error/403/403'
					});
					reject(err)
					executeQueue(err)
				}

			})
	})
}

// 添加请求拦截器
instance.interceptors.request.use(
	config => {
		// 给每条请求赋值 Token 请求头
		config.header['token'] = config.header['token'] || store.state.user.token || uni.getStorageSync(
			'TOKEN') // token令牌

		const requestUid = new Date().getTime() // 请求requestUid,时间戳
		config.data = {
			data: Object.assign({}, config?.data || {}),
			requestUid
		}
		// 在发送请求前做些什么
		return config
	},
	error => {
		// 对请求错误做些什么
		return Promise.reject(error)
	}
)

// 添加响应拦截器
instance.interceptors.response.use(
	response => {
		if (response?.config?.header?.isLog) { // 上报问题接口 无需处理
			return
		}
		errorApiLogUpload(response)
		const {
			code,
			data,
			msg
		} = response.data || {}

		if (code === 200) {
			return response.data
		} else if (code === 201 || code === 202 || code === 203) { // 刷新 Token
			store.commit('user/logout', '')
			uni.reLaunch({
				url: '/pages/error/403/403'
			});
			return Promise.reject(response.data)
			// return refreshTokenHandler(() => instance(response.config))
		} else {
			msg && uni.showToast({
				title: msg,
				position: 'top',
				icon: 'none',
				duration: 2500
			});
			return Promise.reject(response.data)
		}
	},
	error => {
		// 对响应错误做些什么
		return Promise.reject(error)
	}
)

// 导出 create 创建后的实例
export default instance

// 200=成功时状态码
// 201=token超时
// 202=token为空
// 203=token非法
// 402=业务数据配置缺失时错误码
// 403=超出服务范围时，禁止提供服务（熔断，高并发限流）时，错误码
// 500=未定义的系统异常（Exception）时，错误码
// 401=业务未授权时进行访问，401（权限校验）
// 402=方法参数错误
