import axios, { AxiosRequestConfig, Method, AxiosInstance } from 'axios'
//import qs from 'qs'
//import cryptojs from 'crypto-js'
import { addPending, removePending } from './pending'
import { useLoginStore } from '@/stores'
import { HttpParams, CommonParams, HttpResponse, Payload, ResultCode } from './interface'
import service from '@/services'

const httpService = new (class {
    private axiosInstance?: AxiosInstance

    constructor() {
        this.init()
    }

    private init = async () => {
        if (!this.axiosInstance) {
            const config = await service.onReady()
            this.axiosInstance = axios.create({
                timeout: 30000,
                baseURL: config.goCommonSearchUrl,
            })
            // 请求拦截器
            this.axiosInstance.interceptors.request.use(
                (config) => {
                    const { getToken } = useLoginStore()
                    removePending(config) //在请求开始前，对之前的请求做检查取消操作
                    addPending(config) //将当前请求添加到列表中
                    console.log('Token', getToken())
                    //请求头签名
                    const sign = {
                        token: getToken(),
                        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) => {
                    const { msg, message } = err.response.data
                    if (!axios.isCancel(err)) {
                        console.error(err)
                    }
                    // 异常提示待优化
                    return Promise.reject(msg || message || '服务器异常，请稍后再试')
                }
            )
        }
        return Promise.resolve(this.axiosInstance)
    }

    private request = async (url: string, method: Method, params?: unknown) => {
        const requestConfig: AxiosRequestConfig = {
            url,
            method,
        }
        if (params instanceof Object) {
            if (['post', 'POST', 'put', 'PUT', 'patch', 'PATCH'].includes(method)) {
                requestConfig.data = params
            } else {
                requestConfig.params = params
            }
        } else {
            requestConfig.url = url + (params ?? '')
        }
        const instance = await this.init()
        return instance(requestConfig)
    }

    commonRequest = async <T extends Payload>(url: string, method: Method, params: CommonParams<T>) => {
        const { data, success, fail, complete } = params
        await this.request(url, method, data).then((res) => {
            const data = res.data as T['rsp']
            success && success(data)
        }).catch((err) => {
            fail && fail(err)
            return Promise.reject(err)
        }).finally(() => {
            complete && complete()
        })
    }

    httpRequest = async <T extends Payload>(url: string, method: Method, params: HttpParams<T>) => {
        const { data, success, fail, complete } = params
        await this.request(url, method, data).then((res) => {
            const data = res.data as HttpResponse<T['rsp']>
            switch (data.code) {
                case ResultCode.InvalidToken:
                    //退出登录
                    //store.dispatch("user/logout", () => {
                    //    window.location.reload()
                    //})
                    return Promise.reject('令牌无效')
                case ResultCode.Success:
                    success && success(data)
                    return Promise.resolve()
                default:
                    fail && fail(data.msg)
                    return Promise.reject(data.msg)
            }
        }).catch((err) => {
            fail && fail(err)
            return Promise.reject(err)
        }).finally(() => {
            complete && complete()
        })
    }
})

export const { commonRequest, httpRequest } = httpService

/**
 * 获取服务配置地址
 * @param key 
 * @returns 
 */
export function getServiceUrl(key: keyof typeof service.config) {
    return service.config[key]
}