var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var RequestInstruction_exports = {};
__export(RequestInstruction_exports, {
  default: () => RequestInstruction_default
});
module.exports = __toCommonJS(RequestInstruction_exports);
var import_node_fs = __toESM(require("node:fs"));
var import_node_os = __toESM(require("node:os"));
var import_node_path = __toESM(require("node:path"));
var import_server = require("@tego/server");
var import_axios = __toESM(require("axios"));
var import_form_data = __toESM(require("form-data"));
var import_lodash = __toESM(require("lodash"));
var import_mime_types = __toESM(require("mime-types"));
var import__ = require("../..");
async function downloadToStream(resourceUrl, Headers, param, body) {
  try {
    const response = await (0, import_axios.default)({
      method: "GET",
      url: resourceUrl,
      headers: Headers,
      params: param,
      data: body,
      responseType: "stream"
    });
    const ext = import_mime_types.default.extension(Headers["Content-Type"]);
    let tempFileName;
    do {
      tempFileName = `${(0, import_server.uid)()}.${ext}`;
    } while (import_node_fs.default.existsSync(tempFileName));
    const tempFilePath = import_node_path.default.join(import_node_os.default.tmpdir(), tempFileName);
    const writeStream = import_node_fs.default.createWriteStream(tempFilePath);
    response.data.pipe(writeStream);
    return new Promise((resolve, reject) => {
      writeStream.on("finish", () => {
        resolve(import_node_fs.default.createReadStream(tempFilePath));
      });
      writeStream.on("error", (error) => {
        import_node_fs.default.unlinkSync(tempFilePath);
        reject(error);
      });
    });
  } catch (error) {
    console.error("\u4E0B\u8F7D\u6587\u4EF6\u65F6\u51FA\u9519:", error);
    throw error;
  }
}
async function request(config, context) {
  var _a;
  const { token, origin } = context;
  const { method = "POST", needAuthorization = true, data, timeout = 5e3 } = config;
  const originUrl = ((_a = config.url) == null ? void 0 : _a.trim()) || "";
  const url = originUrl.startsWith("http") ? originUrl : `${origin}${originUrl}`;
  let headers = (config.headers ?? []).reduce((result, header) => {
    return Object.assign(result, { [header.name]: header.value });
  }, {});
  const params = (config.params ?? []).reduce(
    (result, param) => Object.assign(result, { [param.name]: param.value }),
    {}
  );
  const requestParams = {
    url,
    method,
    headers,
    params,
    data,
    timeout
  };
  if (needAuthorization) {
    requestParams.headers = {
      Authorization: "Bearer " + token,
      ...headers
    };
  }
  if (headers["Content-Type"] === "multipart/form-data") {
    const formData = new import_form_data.default();
    for (const [key, value] of Object.entries(data)) {
      if (key === "file") {
        let { url: resourceUrl, params: resourceParams, headers: resourceHeader, body: resourceBody } = data[key];
        resourceUrl = (resourceUrl == null ? void 0 : resourceUrl.trim()) || "";
        if (resourceHeader["Content-Type"] === "multipart/form-data" && resourceBody) {
          const formData2 = new import_form_data.default();
          Object.entries(resourceBody).forEach(([key2, value2]) => {
            formData2.append(key2, value2);
          });
          config.data = formData2;
        } else {
          config.data = resourceBody;
        }
        const stream = await downloadToStream(resourceUrl, resourceHeader, resourceParams, resourceBody);
        formData.append("file", stream);
        headers = { ...formData.getHeaders() };
      } else {
        formData.append(key, data[key]);
      }
    }
    requestParams.data = formData;
  } else {
    headers["Content-Type"] = "application/json";
  }
  return import_axios.default.request(requestParams);
}
class RequestInstruction_default extends import__.Instruction {
  async run(node, prevJob, processor) {
    const userId = import_lodash.default.get(processor.getScope(node.id), "$context.user.id", "");
    const origin = import_server.Gateway.getInstance().runAtLoop;
    const token = this.workflow.app.authManager.jwt.sign({ userId });
    const context = { token, origin };
    const config = processor.getParsedValue(node.config, node.id);
    const { workflow } = processor.execution;
    const sync = this.workflow.isWorkflowSync(workflow);
    const loopData = prevJob.result;
    if (loopData["length"]) {
      config.params.push(
        { name: "loopLength", value: loopData["length"] },
        { name: "loopIndex", value: loopData["index"] }
      );
    }
    if (sync) {
      try {
        const response = await request(config, context);
        return {
          status: import__.JOB_STATUS.RESOLVED,
          result: response.data
        };
      } catch (error) {
        return {
          status: import__.JOB_STATUS.FAILED,
          result: error.isAxiosError ? error.toJSON() : error.message
        };
      }
    }
    const job = await processor.saveJob({
      status: import__.JOB_STATUS.PENDING,
      nodeId: node.id,
      nodeKey: node.key,
      upstreamId: (prevJob == null ? void 0 : prevJob.id) ?? null
    });
    request(config, context).then((response) => {
      job.set({
        status: import__.JOB_STATUS.RESOLVED,
        result: response.data
      });
    }).catch((error) => {
      job.set({
        status: import__.JOB_STATUS.FAILED,
        result: error.isAxiosError ? error.toJSON() : error.message
      });
    }).finally(() => {
      processor.logger.info(`request (#${node.id}) response received, status: ${job.get("status")}`);
      this.workflow.resume(job);
    });
    processor.logger.info(`request (#${node.id}) sent to "${config.url}", waiting for response...`);
    return processor.exit();
  }
  async resume(node, job, processor) {
    const { ignoreFail } = node.config;
    if (ignoreFail) {
      job.set("status", import__.JOB_STATUS.RESOLVED);
    }
    return job;
  }
}
