import Vue from 'vue';
import getUrl from '@/services/config/configutils';
import { AxiosRequest, ResponseType, CustomResponse } from './types';
import { LoginParm } from './types/user/userModel';
// import storage from '@/utils/storage';
import { ElLoading, ElMessage } from 'element-plus'
import {store} from '@/store'
// import { ILoadingInstance } from 'element-plus/lib/components/loading'
import qs from 'qs';
import axios, { AxiosRequestHeaders, AxiosInstance, AxiosResponse, AxiosRequestConfig, Method } from 'axios';
import router from '@/router';

// 定义接口
interface PendingType {
    url: string | undefined;
    method: Method | undefined;
    params: object;
    data: object;
    cancel: Function;
}
interface listParms {
    pageNo:number;
    pageSize:number;
}
//加载效果
// let loading: ILoadingInstance;

// 取消重复请求
const pending: Array<PendingType> = [];
const CancelToken = axios.CancelToken;

// 移除重复请求
const removePending = (config: AxiosRequestConfig) => {
    for (const key in pending) {
        const item: number = +key;
        const list: PendingType = pending[key];
        // 当前请求在数组中存在时执行函数体
        if (list.url === config.url && list.method === config.method && JSON.stringify(list.params) === JSON.stringify(config.params) && JSON.stringify(list.data) === JSON.stringify(config.data)) {
            // 执行取消操作
            list.cancel('操作太频繁，请稍后再试');
            // 从数组中移除记录
            pending.splice(item, 1);
        }
    }
};

class BaseHttp {

    sericeAPI: AxiosInstance; //axios实例
    protected baseURL: string = import.meta.env.VITE_APP_BASE_URL;


    //构造函数
    constructor(config?: AxiosRequestConfig) {
        //Object.assign(this.config,_config)//合并
        //创建axios实例
        this.sericeAPI = axios.create(config);
        this.loadInterceptors();
    }

    private loadInterceptors() {

        //拦截请求拦截器，所有请求都将经过此处处理
        this.sericeAPI.interceptors.request.use((config: AxiosRequestConfig) => {
            const token = sessionStorage.getItem('token')
            if (token) {
                config.headers = { 'Authorization': `${token}`, ...config.headers };
            }
            // loading = ElLoading.service({
            //     text: '加载中',
            //     background: 'rgba(0, 0, 0, 0.3)'
            // })
            removePending(config);
            config.cancelToken = new CancelToken((c) => {
                pending.push({ url: config.url, method: config.method, params: config.params, data: config.data, cancel: c });
            });
            return config;
        },
            (error) => {
                return Promise.reject(error);
            }
        );


        //响应请求拦截器
        this.sericeAPI.interceptors.response.use(
            (response: AxiosResponse) => {
                // loading.close();//关闭loading动画
                removePending(response.config);
                switch(response.data.code){
                    case 401:
                        ElMessage.error(response.data.msg)
                        break;
                    case 403:
                        ElMessage.error(response.data.msg)
                        break;
                    case 404:
                        ElMessage.error(response.data.msg)
                        break;
                    case 500:
                        ElMessage.error(response.data.msg)
                        break;
                }
                return response;
            },
            (error) => {
                // loading.close();
                const response = error.response;
                // 根据返回的code值来做不同的处理(和后端约定)
                switch (response.status) {
                    case 401:
                        ElMessage.error('错误请求')
                        break;
                    case 403:
                        // 没有权限
                        ElMessage.error('没有权限')
                        break;
                    case 500:
                        // 服务端错误
                        ElMessage.error('服务端错误(500)')
                        break;
                    case 503:
                        // 服务端错误
                        ElMessage.error('服务端错误(503)')
                        break;
                    default:
                        break;
                }

                // 超时重新请求
                const config = error.config;
                // 全局的请求次数,请求的间隙
                const [RETRY_COUNT, RETRY_DELAY] = [0, 1000];

                if (config && RETRY_COUNT) {
                    // 设置用于跟踪重试计数的变量
                    config.__retryCount = config.__retryCount || 0;
                    // 检查是否已经把重试的总数用完
                    if (config.__retryCount >= RETRY_COUNT) {
                        return Promise.reject(response || { message: error.message });
                    }
                    // 增加重试计数
                    config.__retryCount++;
                    // 创造新的Promise来处理指数后退
                    const backoff = new Promise((resolve) => {
                        setTimeout(() => {
                            resolve('');
                        }, RETRY_DELAY || 1);
                    });
                    // instance重试请求的Promise
                    return backoff.then(() => {
                        return this.sericeAPI(config);
                    });
                }

                // eslint-disable-next-line
                return Promise.reject(response || { message: error.message });
            }
        );


    }




    get<T = any>(url: string, parms?: any): Promise<CustomResponse<T>> {
        return new Promise((resolve, reject) => {
            this.sericeAPI.get<T>(url, {
                params: parms,
                headers:{
                },
                paramsSerializer: (parms) => {
                    return qs.stringify(parms)
                }
            }).then((res) => {
                resolve(res.data as any)
            }).catch((error) => {
                reject(error)
            })
        })
    }

    post<T = any>(url: string, parms: any): Promise<CustomResponse<T>> {
        return new Promise((resolve, reject) => {
            this.sericeAPI.post(url, parms, {
                transformRequest: [(params) => {
                    return JSON.stringify(params)
                }],
                headers: {
                    'Content-Type': 'application/json'
                }
            }).then((res) => {
                resolve(res.data as any)
            }).catch((error) => {
                reject(error)
            })
        })
    }

    delete<T = any>(url: string, parms: any): Promise<CustomResponse<T>> {
        return new Promise((resolve, reject) => {
            this.sericeAPI.delete(url, {
                params:parms
            }).then((res) => {
                resolve(res.data as any)
            }).catch((error) => {
                reject(error)
            })
        })
    }

    put<T = any>(url: string, parm: any): Promise<CustomResponse<T>> {
        return new Promise((resolve, reject) => {
            this.sericeAPI.put(url,parm).then((res) => {
                resolve(res.data as any)
            }).catch((error) => {
                reject(error)
            })
        })
    }


    getImage(url: string) {
        return this.sericeAPI.get(url)
        //   })
    }


    //登录
    login<T = any>(url: string, parms: LoginParm): Promise<CustomResponse<T>> {
        return new Promise((resolve, reject) => {
            this.sericeAPI.post<T>(url, parms, {
                transformRequest: [(parms) => {
                    return qs.stringify(parms)
                }],
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                }
            }).then((res) => {
                resolve(res as any)
            }).catch((error) => {
                reject(error)
            })
        })
    }

    //分页查询
    list<T = any>(url: string, parms?: listParms): Promise<CustomResponse<T>> {
        return new Promise((resolve, reject) => {
            this.sericeAPI.get<T>(url, {
                params: parms,
                headers:{
                },
                paramsSerializer: (parms) => {
                    return qs.stringify(parms)
                }
            }).then((res) => {
                resolve(res.data as any)
            }).catch((error) => {
                reject(error)
            })
        })
    }

}



export default BaseHttp;
