import { Response } from "@/types";
import { Toast } from "antd-mobile";
import axios, { AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from "axios";
import type { AxiosOptions } from "./type";

import { locales } from "@/i18n";
import { getCookies, getToken } from "@/utils/Cookies";

interface CustomRequestConfig {
    toast?: boolean;
}

export default class Request {
    private axiosInstance: AxiosInstance;
    private readonly options: AxiosOptions;
    constructor(options: AxiosOptions) {
        this.axiosInstance = axios.create(options);
        this.options = options;
        this.setupInterceptors();
    }

    setupInterceptors() {
        // 定义拦截器
        const {
            options: { transform },
            axiosInstance,
        } = this;
        // 如果没有自定义拦截器则返回
        if (!transform) {
            return;
        }
        // 解包拦截器
        const {
            requestInterceptor,
            requestInterceptorCatch,
            responseInterceptor,
            responseInterceptorCatch,
        } = transform;
        /**
         * @description 全局请求拦截
         */
        axiosInstance.interceptors.request.use(
            async (config: InternalAxiosRequestConfig & CustomRequestConfig) => {
                if (requestInterceptor) {
                    config = requestInterceptor(config);
                    // header请求头添加token
                    config.headers["Token"] = getToken() || "";
                    config.headers["language"] =
                        getCookies("language") === "br"
                            ? "pt"
                            : getCookies("language") || locales.at(2);
                    if (config && config?.toast) {
                        Toast.show({
                            icon: "loading",
                            duration: 0,
                            maskClickable: false,
                        });
                    }
                }

                return config;
            },
            (error) => {
                if (requestInterceptorCatch) {
                    requestInterceptorCatch(error);
                }
            }
        );
        /**
         * @description 全局响应拦截
         */
        axiosInstance.interceptors.response.use(
            (res) => {
                Toast.clear();
                if (responseInterceptor) {
                    res = responseInterceptor(res);
                }
                return res;
            },
            (error) => {
                if (responseInterceptorCatch) {
                    responseInterceptorCatch(error);
                }
                Toast.clear();
            }
        );
    }

    /**
     * @description 单个实列请求
     */
    request<T = unknown, R = unknown>(config: AxiosOptions): Promise<Response<T> & R> {
        return new Promise((resolve, reject) => {
            this.axiosInstance
                .request<unknown, AxiosResponse<Response<T> & R>>(config)
                .then((res) => {
                    const { transform } = config;
                    if (transform && transform.responseInterceptor) {
                        res = transform.responseInterceptor(res);
                    }
                    if (res && res.data && res.data.code === 200) {
                        resolve(res.data);
                    } else {
                        // if (res && res.data && res.data.msg) {
                        //     Toast.show(res.data.msg || "请求失败");
                        // }
                        reject(res);
                    }
                })
                .catch((error) => {
                    reject(error);
                });
        });
    }
    get<T, R = unknown>(config: AxiosOptions): Promise<Response<T> & R> {
        return this.request({ ...config, method: "get" });
    }
    post<T, R = unknown>(config: AxiosOptions): Promise<Response<T> & R> {
        return this.request({ ...config, method: "post" });
    }
    put<T, R = unknown>(config: AxiosOptions): Promise<Response<T> & R> {
        return this.request({ ...config, method: "put" });
    }
    delete<T, R = unknown>(config: AxiosOptions): Promise<Response<T> & R> {
        return this.request({ ...config, method: "delete" });
    }
}
