import Wreck from "@hapi/wreck";
import * as R from "remeda";
import { withDb, AppDatabase } from "../db";
import logger from "../logger";

export interface WebhookOptions {
  webhookId: string;
  payload: any;
}

const notifyWebhooksTask = async (options: WebhookOptions): Promise<void> =>
  withDb(async (db: AppDatabase) => {
    const { webhookId, payload } = options;

    const webhook = await db.webhooks.findById({ id: webhookId });
    if (!webhook) {
      logger.debug(
        { webhookId },
        "notify-webhook: no webhook registered with id"
      );
      return;
    }

    const { endpointUrl, httpMethod, headers } = webhook;
    const headersFormatted = R.reduce(
      headers || [],
      (acc: any, h: any) => {
        acc[h.header] = h.value;
        return acc;
      },
      {}
    );

    const wreck = Wreck.defaults({
      json: true,
      headers: headersFormatted,
    });

    // http errors will bubble up and cause the job to fail and be retried
    try {
      logger.debug(
        { webhookId, endpointUrl, httpMethod },
        "notify-webhook: notifying"
      );
      await (httpMethod === "post"
        ? wreck.post(endpointUrl, { payload })
        : wreck.put(endpointUrl, { payload }));
    } catch (error: any) {
      logger.error(
        { webhookId, error: error.output },
        "notify-webhook failed with this error"
      );
      throw new Error(`webhook failed webhookId=${webhookId}`);
    }
  });

export default notifyWebhooksTask;
