import {
  Plugable
} from "./chunk-GN6QC5RS.mjs";
import {
  getHttpMethods,
  isArrowFunction,
  mergeDeep
} from "./chunk-FKHYE7Y6.mjs";

// src/fn.ts
import debug from "debug";
var log = debug("@tomrpc/core/fn");
var Fn = class extends Plugable {
  constructor(cfg) {
    super(
      mergeDeep(
        {
          prefix: "/api",
          functions: []
        },
        cfg
      )
    );
    this.name = "Fn";
    this.prefix = this.config.prefix;
    this.app.use(this.compose([this.before(), this.mount(), this.default()]));
  }
  fn(key, fn) {
    if (!this.config["functions"])
      this.config["functions"] = {};
    const pre = key.split("")[0] == "/" ? "" : "/";
    this.config["functions"][pre + key] = fn;
  }
  add(items) {
    for (const [name, fn] of Object.entries(items)) {
      if (isArrowFunction(fn)) {
        console.log(
          `this.rpcFunctions[${name}] is arrow function, please use ctx as param, not this`
        );
      }
      if (this.config["functions"][name]) {
        log(`add ${name}: ${fn}`);
        console.log(`this.rpcFunctions[${name}] exisit`);
      }
      this.fn(name, fn);
    }
  }
  default() {
    return async (ctx, next) => {
      log("default");
      ctx.body = "[fn plugin] no fn repsonse, please check your fn if exist";
      log("default end");
    };
  }
  mount() {
    return async (ctx, next) => {
      log(this);
      const routers = this.config["functions"];
      log(routers);
      const path = ctx.path;
      log("mountMiddleware" + ctx.path);
      const key = "/" + path.replace("/", "").split("/").join(".");
      if (!["POST", "PUT", "PATCH"].includes(ctx.method) && !ctx.query.$p) {
        console.log("not match $p param, no process");
        ctx.body = "not match $p param, no process";
      } else {
        const param = ctx.method === "POST" ? ctx.request.body : JSON.parse(ctx.query.$p);
        log(key);
        log(param);
        log(routers[key]);
        if (routers[key]) {
          const args = [...param, ctx];
          console.dir(`call fn ${ctx.path}, with [${param}]`);
          const result = routers[key].apply(ctx, args);
          ctx.body = result;
        } else {
          const msg = JSON.stringify(ctx, null, 4);
          ctx.body = ` not match path ${ctx.path}  
 ctx = ${msg}`;
          await next();
        }
      }
    };
  }
  before() {
    return async (ctx, next) => {
      log("pre");
      const key = ctx.path.replace("/", "").split("/").join(".");
      const lastKey = key.split(".").pop();
      const httpMethods = getHttpMethods();
      const supportMethods = [];
      httpMethods.forEach(function(m) {
        if (lastKey.indexOf(m) != -1) {
          log(m);
          supportMethods.push(m);
          return m;
        }
      });
      if (supportMethods.length === 0) {
        log(ctx.path + ",\u6CA1\u6709\u5339\u914D\u5230\u5305\u542Bget/post\u7B49\u5F00\u5934\u7684\u51FD\u6570");
        await next();
      } else if (ctx.method === supportMethods[0]) {
        log("\u5339\u914D\u5230\u5305\u542Bget/post\u7B49\u65B9\u6CD5\u7684\u51FD\u6570");
        await next();
      } else {
        log("\u5339\u914D\u5230\u5305\u542Bget/post\u7B49\u65B9\u6CD5\u7684\u51FD\u6570\uFF0C\u4F46method\u4E0D\u5BF9");
        ctx.body = "process fn:" + lastKey + " , you need send " + supportMethods[0] + " request from client";
      }
    };
  }
};

export {
  Fn
};
