import { AxiosRequestConfig } from "axios";
import { request } from "ice";
import common from "./common";
import auth from "./auth";
import designer from "./designer";
import { message } from "antd";

interface IRequestConfig extends AxiosRequestConfig {
  instanceName?: string;
  withFullResponse?: boolean;
  form?: boolean;
  defaultValue?: JSONObject;
  // 内部捕获错误,默认true
  catchError?: boolean;
  [key: string]: any;
}

/**
 * 接口请求的统一封装处理
 */

interface ApiConfig {
  method: string;
  url?: string;
  headers?: {
    "Content-Type": string;
  };
}

type IApiConfig<T> = {
  [K in keyof T]: {
    url: string;
    method: string;
  };
};

type IApiMap<T> = {
  [K in keyof T]: IApiConfig<T[K]>;
};

/**
 * 转换各个api为标准的ApiConfig结构
 * {xxx: '/a/b/c', yyy: {url: 'd/e/f', method: 'POST', form: true}
 * {xxx: {url: '/a/b/c'}, yyy: {url: 'd/e/f', method: 'POST', headers: {'Content-Type': 'application/x-www-form-urlencoded'}}}
 */
function transApiObject<T extends Object>(apiValue: T) {
  const apiValueMap = {};
  Object.keys(apiValue).forEach((key) => {
    // 默认请求方式POST
    const apiConfig: ApiConfig = {
      method: "POST",
    };

    if (typeof apiValue[key] == "string") {
      apiConfig.url = `${apiValue[key]}`;
    } else {
      const { url, form, method = "POST" } = apiValue[key];
      apiConfig.url = `${url}`;
      apiConfig.method = method;
      if (form) {
        apiConfig.headers = {
          "Content-Type": "application/x-www-form-urlencoded",
        };
      }
    }
    apiValueMap[key] = apiConfig;
  });
  return apiValueMap;
}

function transApi<T extends Object>(apiMap: T): IApiMap<T> {
  const transApiMap = {};
  Object.keys(apiMap).forEach((apiName) => {
    transApiMap[apiName] = transApiObject(apiMap[apiName]);
  });
  return transApiMap as IApiMap<T>;
}

export const apis = transApi({ common, auth, designer });

type IRequestMap<T> = {
  [K in keyof T]: (requestConfig?: IRequestConfig) => Promise<JSONObject>;
};

type IRequestModule<T> = {
  [K in keyof T]: IRequestMap<T[K]>;
};

export const proxyApi = (function <T extends Object>(apis: T) {
  const apiModuleKeys = Reflect.ownKeys(apis);
  const proxyApiMap = {};
  apiModuleKeys.forEach((module) => {
    proxyApiMap[module] = new Proxy(apis[module], {
      get(target, prop) {
        return (requestConfig: IRequestConfig) => {
          const {
            method,
            form,
            defaultValue = {},
            data = {},
            withFullResponse = false,
            catchError = true,
            ...rest
          } = requestConfig || {};
          const currentApiConfig = target[prop];
          const { url, form: isFormReq = false } =
            typeof currentApiConfig == "string"
              ? { url: currentApiConfig }
              : currentApiConfig;
          const options: IRequestConfig = {
            url: `${url}`,
            baseURL: location.hostname == "localhost" ? "/api" : "",
            method: method || "POST",
            withFullResponse,
            data: Array.isArray(requestConfig)
              ? [...requestConfig]
              : {
                  ...defaultValue,
                  ...data,
                  ...rest,
                },
          };
          // 是否使用form表单提交数据
          if (form || isFormReq) {
            options.headers = {
              "Content-Type": "application/x-www-form-urlencoded",
            };
          }
          if (catchError) {
            return request(options).catch((error) => {
              message.error(error?.response?.data?.message || "请求错误");
            });
          }
          return request(options);
        };
      },
    });
  });
  return proxyApiMap as IRequestModule<T>;
})({ common, auth, designer });
