import axios, { AxiosRequestConfig } from 'axios'
//import qs from 'qs'
//import cryptojs from 'crypto-js'
//import { addPending, removePending } from './pending'
import { useLoginStore } from '@/stores'
import { CommonResult, ResultCode } from './interface'
import service from '@/services'

export default new (class {
    private readonly axiosInstance = axios.create({
        timeout: 30000,
    })

    constructor() {
        const loginStore = useLoginStore()

        // 请求拦截器
        this.axiosInstance.interceptors.request.use(
            (config) => {
                //addPending(config) //将当前请求添加到列表中
                //请求头签名
                const sign = {
                    token: loginStore.token,
                    signsecret: 'qz7qWOMXKTMT5JlDs5w4NTPwWeR3xhF1v6wqbZ9cExmP6cc3spvNAp1wJJ1SqRI5',
                    timestamp: new Date().getTime(),
                }
                //设置请求头
                config.headers = {
                    Authorization: sign.token,
                    //Signid: 'eecd3f37625f4501b88e9f0fa14b4b51',
                    //Sign: cryptojs.SHA256(qs.stringify(sign)).toString(),
                    //Timestamp: sign.timestamp.toString(),
                }
                return config
            },
            (err) => {
                console.error(err)
                return Promise.reject('发生错误，请稍后再试')
            }
        )

        // 响应拦截器
        this.axiosInstance.interceptors.response.use(
            (res) => {
                //removePending(res) //在请求结束后，移除本次请求
                return res
            },
            (err) => {
                if (err.message === 'Network Error') {
                    return Promise.reject('无效的网络连接')
                }
                if (err.response) {
                    const { msg, message } = err.response.data ?? {}
                    switch (err.response.status) {
                        case 408: {
                            return Promise.reject('请求超时，请稍后再试')
                        }
                        default: {
                            return Promise.reject(msg || message)
                        }
                    }
                }
                return Promise.reject('发生错误，请稍后再试')
            }
        )
    }

    /** 
     * 是否启用响应延时
     * 可防止在动画过程中同时请求数据，数据请求先于动画完成，双绑数据的页面会重新渲染，导致动画卡顿的问题
     */
    private delay = false

    /** 如果启用响应延时，将响应回调添加到该集合中 */
    private resultMap = new Set<() => void>()

    /** 请求时的 loading 状态 */
    get loading() {
        return this.delay
    }

    /** 在动画开始时设置一个 loading 状态，在动画结束后取消 loading 状态，后返回请求结果 */
    set loading(status: boolean) {
        this.delay = status
        if (!status) {
            // 当 loading 状态为 false 时返回所有延时请求的回调
            this.resultMap.forEach((fn) => {
                fn()
                this.resultMap.delete(fn)
            })
        }
    }

    /**
     * Http 请求
     * @param config 
     * @param errMsg 
     * @returns 
     */
    request<T>(config: AxiosRequestConfig, errMsg?: string) {
        return new Promise<T>((resolve, reject) => {
            this.axiosInstance(config).then((res) => {
                if (this.delay) {
                    this.resultMap.add(() => resolve(res.data))
                } else {
                    resolve(res.data)
                }
            }).catch((err) => {
                const msg = err ?? (errMsg ? '请求失败: ' + errMsg : '请求失败，请稍后重试')
                reject(msg)
            })
        })
    }

    /**
     * Http 通用请求
     * @param config 
     * @param errMsg 
     * @returns 
     */
    async commonRequest<T>(config: AxiosRequestConfig, errMsg?: string) {
        const baseUrl = service.getConfig('goCommonSearchUrl')
        config.url = baseUrl + config.url
        const res = await this.request<CommonResult<T>>(config, errMsg)
        switch (res.code) {
            case ResultCode.InvalidToken:
                return Promise.reject('令牌无效')
            case ResultCode.Success:
                return res
            default:
                return Promise.reject(res.msg)
        }
    }
})