import axios from "axios";
import paths from "./paths.json";
import { Client } from "./client";

const callApi = (
  baseUrl: string,
  token: string,
  methodPath: string,
  params: any,
): Promise<any> => {
  console.log("call", methodPath);
  const methodValue = (paths as any)[methodPath];
  if (!methodValue) {
    throw new Error("未能找出对应api路径");
  }

  const { parameters, method } = methodValue;
  let { path } = methodValue;
  parameters
    .filter((item: any) => item.in === "path")
    .forEach((item: any) => {
      path = path.replace(`{${item.name}}`, (params as any)[item.name]);
    });

  const queryParams: any = {};
  parameters
    .filter((item: any) => item.in === "query")
    .forEach((item: any) => {
      queryParams[item.name] = (params as any)?.[item.name];
    });
  const bodyParams: any = {};
  parameters
    .filter((item: any) => item.in === "body")
    .forEach((item: any) => {
      Object.assign(bodyParams, (params as any)?.[item.name] || {});
    });
  const apiPath = `${baseUrl}${path}`;
  console.log("api call", apiPath, method);
  return axios({
    method,
    url: apiPath,
    headers: {
      Authorization: `Bearer ${token}`,
      accept: "application/json",
    },
    params: queryParams,
    data: bodyParams,
  }).then((res: any) => res.data) as Promise<any>;
};

export const getClient = (baseUrl: string, token: string): Client => {
  function getProxyForPath(path: string) {
    const methodValue = (paths as any)[path];
    if (methodValue) {
      return (params: any) => callApi(baseUrl, token, path, params);
    } else {
      return new Proxy(
        {},
        {
          get(target, prop) {
            return getProxyForPath(path + "." + String(prop));
          },
        },
      );
    }
  }
  function getProxyForTagMethod(tag: string) {
    return new Proxy(
      {},
      {
        get(target, method) {
          const path = Object.keys(paths).find((path) => {
            const item = (paths as any)[path];
            console.log("find method", item, tag, method);
            return item.tags[0] === tag && item.operationId === method;
          });
          const methodValue = (paths as any)[path];
          if (!methodValue) {
            throw new Error(`未能找到对应的api路径: ${tag} ${String(method)}`);
          }
          return (params: any) => callApi(baseUrl, token, path, params);
        },
      },
    );
  }

  return new Proxy(
    {},
    {
      get: (target, prop: string) => {
        console.log("get prop", prop);
        if (/^[A-Z]/.test(prop.charAt(0))) {
          return getProxyForTagMethod(prop);
        } else {
          return getProxyForPath(String(prop));
        }
      },
    },
  ) as Client;
};
