import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import axios from 'axios';
import type { Result } from './axios.d';
import { NsMessage } from '/nerv-lib/component/message';
import { routerConfig } from '/nerv-base/config/router.config';
import { Cookies } from '/nerv-lib/util/cookie';
import { RequestEnum } from '/@/enum/http-enum.ts';

export class NSAxios {
  private instance: AxiosInstance;
  private readonly options: AxiosRequestConfig;
  public apiModule: any = {};
  public projectType = 'web';
  public errorMsgKey = 'axiosError'; // 接口错误值有一个提示消息

  constructor(options: AxiosRequestConfig) {
    this.options = options;
    this.instance = axios.create(this.options);
    // this.getModuleList(ApiModule);
    this.interceptors();
  }

  public setTimeout(timeout: number) {
    this.options.timeout = timeout;
    this.instance = axios.create(this.options);
    this.interceptors();
  }
  public setHeaders(headers: any) {
    this.options.headers = Object.assign(this.options.headers, headers);
    this.instance = axios.create(this.options);
    this.interceptors();
  }

  private get modules(): Recordable {
    const list: Recordable = {};
    Object.keys(this.apiModule).forEach((app) => {
      this.apiModule[app].forEach((item: string) => {
        list[item] = app;
      });
    });
    return list;
  }

  private interceptors(): void {
    this.instance.interceptors.request.use((config: AxiosRequestConfig) => {
      // config.headers.token = Cookies.get('nervsid');
      // config.withCredentials = true;
      if (!config.headers) {
        config.headers = {};
      }

      if (Cookies.get('nervsid')) {
        config.headers['token'] = Cookies.get('nervsid');
      }

      //暂时停用后端自己处理
      // const projectId = sessionStorage.getItem('projectId');
      //
      // if (projectId) {
      //   config.headers['X-Nerv-Auth'] = `projectId="${projectId}"`;
      // }

      const { url } = config;

      if (url && !url.startsWith('http')) {
        if (!url.startsWith('/')) {
          let module = '';
          if (url.includes('/')) module = url.split('/')[0];
          if (this.modules.hasOwnProperty(module))
            config.url = `/api/${this.modules[module]}/objs/${url}`;
        }

        if (this.projectType !== 'web') config.url = `/${this.projectType}/${url}`;
      }
      return config;
    }, undefined);

    const errCodeMap = new Map<number, any>([
      [13, ''],
      [1, ''],
      [10086, () => routerConfig.logout()],
    ]);

    // type closeType = (() => void) | undefined;
    this.instance.interceptors.response.use(
      (res: AxiosResponse) => {
        // todo
        const code = res?.data?.retcode;
        const msg = res?.data?.msg;
        if (errCodeMap.has(code)) {
          console.log(errCodeMap.get(code));

          NsMessage.error({
            content: msg,
            key: this.errorMsgKey,
            onClose: errCodeMap.get(code) && errCodeMap.get(code)(),
          });
          return Promise.reject(res);
        }
        return res;
      },
      (error: any) => {
        console.log('error', error);
        const { response, code, message } = error || {};
        const msg: string = (response?.data?.msg || response?.data?.message) ?? '';
        const err: string = error?.toString?.() ?? '';
        let errMessage = response?.data || '';
        try {
          if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
            errMessage = '接口请求超时,请刷新页面重试!';
          }
          if (err?.includes('Network Error')) {
            errMessage = '网络异常,请检查您的网络连接是否正常!';
          }
          if (errMessage && !msg) {
            NsMessage.error({ content: errMessage, key: this.errorMsgKey });
            return Promise.reject(error);
          }
        } catch (error) {
          throw new Error(error as string);
        }
        switch (error?.response?.status) {
          case 403:
            errMessage = '用户没有权限';
            //sass项目判断用户是否需要重新登录
            if (response?.data?.code === 'idass.account.NeedLogin') {
              routerConfig.logout();
            }
            if (response?.data?.code === 'idass.account.OrganizationDisable') {
              routerConfig.logout();
            }
            if (response?.config?.url.includes('CheckAuthorization')) {
              routerConfig.logout();
            }
            break;
          case 404:
            errMessage = '链接不存在';
            break;
          default:
            errMessage = msg;
        }
        if (errMessage) {
          if (response?.data?.code === 'idass.account.AccountPwdCheckFail') {
            // NsMessage.error('原密码错误');
            NsMessage.error({ content: errMessage, key: this.errorMsgKey });
          } else {
            if (response.data.fieldErrors !== undefined) {
              NsMessage.error({
                content: JSON.stringify(response.data.fieldErrors).substring(
                  1,
                  JSON.stringify(response.data.fieldErrors).length - 1,
                ),
                key: this.errorMsgKey,
              });
            } else {
              NsMessage.error({ content: errMessage, key: this.errorMsgKey });
            }
          }
        } else {
          // NsMessage.error(error?.response.data?.error, 1);
        }
        return Promise.reject(error);
      },
    );
  }

  request<T = any>(config: AxiosRequestConfig): Promise<T> {
    return new Promise((resolve, reject) => {
      const methodTransform = {
        ...config,
        method: RequestEnum[config.method?.toLocaleUpperCase()],
      };

      this.instance
        .request<any, AxiosResponse<Result>>(methodTransform)
        .then((res: AxiosResponse<Result>) => {
          resolve(res.data as unknown as Promise<T>);
        })
        .catch((e: Error) => {
          reject(e);
        });
    });
  }
  customRequest<T = any>(config: AxiosRequestConfig): Promise<T> {
    return new Promise((resolve, reject) => {
      this.instance
        .request<any, AxiosResponse<Result>>(config)
        .then((res: AxiosResponse<Result>) => {
          resolve(res as unknown as Promise<T>);
        })
        .catch((e: Error) => {
          reject(e);
        });
    });
  }

  get<T = any>(url: string, params?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.request({ url, params, ...config, method: 'GET' });
  }

  post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.request({ url, data, ...config, method: 'POST' });
  }
  put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.request({ url, data, ...config, method: 'PUT' });
  }

  delete<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.request({ url, data, ...config, method: 'DELETE' });
  }
  customPost<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.customRequest({ url, data, ...config, method: 'POST' });
  }
  customGet<T = any>(url: string, params?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.customRequest({ url, params, ...config, method: 'GET' });
  }
}