import axios from 'axios'
import router from '@/router/index'
import { useGlobalStore, useUserInfoStore } from '@/stores'
import { ElMessage } from 'element-plus'

// 扩展 AxiosRequestConfig 接口
declare module 'axios' {
	interface AxiosRequestConfig {
		loading?: boolean
		loadingDom?: any
		repeatRequest?: boolean
		meta?: {
			responseAll?: boolean
		}
	}
}

// 创建axios实例
// console.log(import.meta.env,123)

const service = axios.create({
	//   baseURL: import.meta.env.VITE_APP_URL, // api的base_url
	timeout: 60000 // 请求超时时间
})
if (import.meta.env.MODE != 'development') {
	service.defaults.baseURL = import.meta.env.VITE_APP_URL
}
axios.defaults.headers.post['Content-Type'] = 'application/json'
axios.defaults.headers.post['lang'] = 'en' //配置语言请求头
axios.defaults.withCredentials = true //跨域携带cookie

// request拦截器
service.interceptors.request.use(
	(config: any) => {
		if (removePending(config) && config.loading) closeLoading()
		// 如果repeatRequest不配置，那么默认该请求就取消重复接口请求
		!config.repeatRequest && addPending(config)
		// 打开loading
		if (config.loading) openLoading(config.loadingDom)
		// 如果登录了，有token，则请求携带token
		// Do something before request is sent
		const token = useUserInfoStore().state.token
		if (token) {
			config.headers.Authorization = token // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
			//   config.headers['X-Token'] = getLocal('token') // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
		}
		return config
	},
	(error) => {
		// Do something with request error
		console.log(error) // for debug
		Promise.reject(error)
	}
)

// respone拦截器
service.interceptors.response.use(
	// response => response,
	/**
	 * 下面的注释为通过response自定义code来标示请求状态，当code返回如下情况为权限有问题，登出并返回到登录页
	 * 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中
	 */
	(response: any) => {
		// 如果是llm/streamChat这样的流式接口,不走这样的处理
		if (response.config.url.includes('llm/streamChat')) {
			return response
		}
		// 如果是二进制下载（blob/arraybuffer），直接返回原始 response 以便调用方处理文件
		if (
			response.config.responseType === 'blob' ||
			response.config.responseType === 'arraybuffer' ||
			response.headers['content-type'] === 'application/octet-stream'
		) {
			removePending(response.config)
			if (response.config.loading) closeLoading()
			return response
		}

		// 已完成请求的删除请求中数组
		removePending(response.config)
		// 关闭loading
		if (response.config.loading) {
			closeLoading()
		}
		const res = response.data
		// 处理异常的情况
		// console.log(res)
		if (res.errCode != 0) {
			let msg = res.errMsg || res.message || 'error'
			ElMessage.error(msg)
			return Promise.reject(new Error(msg))
		} else {
			// 默认只返回data，不返回状态码和message
			// 通过 meta 中的 responseAll 配置来取决后台是否返回所有数据(包括状态码，message和data)
			const isbackAll = response.config.meta && response.config.meta.responseAll
			if (isbackAll) {
				return res
			} else {
				return res.data
			}
		}
	},
	(error) => {
		if (error?.response) {
			if (error.config?.loading) closeLoading() // 关闭loading
			if (error?.response?.status === 401) {
				//如果是记录浏览器页面就不跳转login
				// showConfirmDialog({
				// 	title: '确定登出',
				// 	message: '你已被登出，可以取消继续留在该页面，或者重新登录',
				// 	confirmButtonText: '重新登录',
				// 	cancelButtonText: '取消'
				// }).then(() => {
				// store.loginOut().then(() => {
				// 	location.reload() // 为了重新实例化vue-router对象 避免bug
				// })
				// })
				ElMessage({
					type: 'error',
					message: 'Please log in and try again.',
					duration: 5000
				})
				useUserInfoStore().logout()
				return Promise.reject(false)
			}
			error.config && removePending(error.config)
			// console.log('err', error) // for debug
			ElMessage.error(error.response?.data?.message || error.message)
		}
		return Promise.reject(error)
	}
)

// --------------------------------取消接口重复请求的函数-----------------------------------
// axios.js
const pendingMap = new Map()
/**
 * 生成每个请求唯一的键
 * @param {*} config
 * @returns string
 */
function getPendingKey(config: any) {
	const { url, method, params } = config
	let { data } = config
	if (typeof data === 'string') data = JSON.parse(data) // response里面返回的config.data是个字符串对象
	return [url, method, JSON.stringify(params), JSON.stringify(data)].join('&')
}

/**
 * 储存每个请求唯一值, 也就是cancel()方法, 用于取消请求
 * @param {*} config
 */
function addPending(config: any) {
	const pendingKey = getPendingKey(config)
	config.cancelToken =
		config.cancelToken ||
		new axios.CancelToken((cancel) => {
			if (!pendingMap.has(pendingKey)) {
				pendingMap.set(pendingKey, cancel)
			}
		})
}
/**
 * 删除重复的请求
 * @param {*} config
 */
function removePending(config: any) {
	// const pendingKey = getPendingKey(config)
	// if (pendingMap.has(pendingKey)) {
	// 	const cancelToken = pendingMap.get(pendingKey)
	// 	cancelToken(pendingKey)
	// 	pendingMap.delete(pendingKey)
	// 	return true
	// }
}
// ----------------------------------loading的函数-------------------------------
const LoadingInstance: { _count: number } = {
	_count: 0
}
function openLoading(loadingDom: any) {
	LoadingInstance._count++
	// if(LoadingInstance._count === 1) {
	useGlobalStore().setLoading(true)
	// }
}
function closeLoading() {
	if (LoadingInstance._count > 0) LoadingInstance._count--
	if (LoadingInstance._count === 0) {
		useGlobalStore().setLoading(false)
	}
}

export default service
