import { AccessToken, RefreshAccessToken } from '@/common/cache';
import type { RequestConfig } from '@umijs/max';
import { history } from '@umijs/max';
import { message, notification } from 'antd';

export const LOGIN_PATH = '/login';
export const BIZ_ERROR = 'BizError';

// 错误处理方案： 错误类型
enum ErrorShowType {
    SILENT = 0,
    WARN_MESSAGE = 1,
    ERROR_MESSAGE = 2,
    NOTIFICATION = 3,
    REDIRECT = 9,
}

interface ResponseStructure {
    code: number;
    success: boolean;
    data: API.ResponseType<any>;
    errorCode?: number;
    errorMessage?: string | { [key: string]: string }[];
    showType?: ErrorShowType;
}

const requestConfig: RequestConfig = {
    baseURL: AppConfig?.apiRoot ?? '',
    timeout: 30000,
    withCredentials: false,
    errorConfig: {
        errorHandler: (error: any, opts: any) => {
            if (opts?.skipErrorHandler) throw error;

            const notAuth = () => {
                // message.error('用户登录已过期，请重新登录');
                const lpt = location.pathname;
                if (lpt.toLowerCase() !== LOGIN_PATH) {
                    // message.error('未登录！');
                    history.push(`${LOGIN_PATH}?redirect=${location.pathname}`);
                }
            }

            // 我们的 errorThrower 抛出的错误。
            if (error.name === BIZ_ERROR) {
                const errorInfo: ResponseStructure | undefined = error.info;
                if (errorInfo?.code === 401) {
                    notAuth();
                    return;
                }
                if (errorInfo) {
                    const { errorMessage, errorCode } = errorInfo;
                    let errMsg = JSON.stringify(errorMessage);
                    // if(errorMessage instanceof Array){
                    //     errMsg = JSON.stringify(errorMessage);
                    // }
                    // else{
                    //     errMsg = errorMessage;
                    // }
                    switch (errorInfo.showType) {
                        case ErrorShowType.SILENT:
                            // do nothing
                            break;
                        case ErrorShowType.WARN_MESSAGE:
                            message.warning(errMsg);
                            break;
                        case ErrorShowType.ERROR_MESSAGE:
                            message.error(errMsg);
                            break;
                        case ErrorShowType.NOTIFICATION:
                            notification.open({
                                description: errMsg,
                                message: errorCode,
                            });
                            break;
                        case ErrorShowType.REDIRECT:
                            // TODO: redirect
                            break;
                        default:
                            message.error(errMsg);
                    }
                }
            } else if (error.response) {
                // Axios 的错误
                // 请求成功发出且服务器也响应了状态码，但状态代码超出了 2xx 的范围
                if (error.response.status === 401) {
                    notAuth();
                } else {
                    message.error(`响应状态：${error.response.status}`);
                }
            } else if (error.request) {
                // 请求已经成功发起，但没有收到响应
                // \`error.request\` 在浏览器中是 XMLHttpRequest 的实例，
                // 而在node.js中是 http.ClientRequest 的实例
                message.error('无响应，请重试！');
            } else {
                // 发送请求时出了点问题
                message.error('请求错误，请重试！');
            }
        },
    },
    requestInterceptors: [
        (url, config) => {
            const { withoutAuth, data } = config;
            let auth = {};
            if (!withoutAuth) {
                const accessToken = AccessToken.get();
                if (accessToken) {
                    auth = { Authorization: `Bearer ${accessToken.token}` };
                    const dt = new Date().getTime();
                    if (accessToken.value.expireTime < dt) {
                        const refreshToken = RefreshAccessToken.get();
                        if (refreshToken) {
                            auth = { ...auth, 'X-Authorization': `Bearer ${refreshToken.token}` };
                        }
                    }
                }
            }
            let headers = { ...auth };
            if (!(data instanceof FormData)) {
                headers = {
                    Accept: 'application/json',
                    'Content-Type': 'application/json',
                    ...auth,
                };
            }
            return { options: { ...config, headers }, url };
        },
    ],
    responseInterceptors: [
        (response) => {
            const accessToken = response.headers['access-token'];
            const xAccessToken = response.headers['x-access-token'];
            if (accessToken && accessToken !== 'invalid_token') {
                AccessToken.set(accessToken);
            }
            if (xAccessToken) {
                RefreshAccessToken.set(xAccessToken);
            }
            if (response.config?.responseType === 'blob') {
                return response;
            }
            const resData = response?.data as unknown as API.ResponseType<any>;
            if (!resData?.success) {
                throw {
                    name: BIZ_ERROR,
                    info: {
                        code: resData?.code,
                        success: false,
                        errorCode: resData?.errorCode,
                        errorMessage: resData?.errorMessage,
                        showType: ErrorShowType.ERROR_MESSAGE,
                        data: resData?.data,
                    },
                };
            }
            return response;
        },
    ],
};

export default requestConfig;
