import { sleepSeconds } from './sleep.ts';
import { WEBHOOK_ENDPOINT } from 'astro:env/server';
import { logger } from '@util/log.ts';

export enum WebhookAction {
  Signup = 'signup',
  Report = 'report',
  Strike = 'strike'
}

export type WebhookActionType<T extends WebhookAction> = {
  [WebhookAction.Signup]: {
    firstname: string;
    lastname: string;
    birthday: string;
    telephone: string | null;
    username: string;
    edition: 'java' | 'bedrock';
    uuid: string | null;
  };
  [WebhookAction.Report]: {
    reporter: string | null;
    reported: string | null;
    reason: string;
  };
  [WebhookAction.Strike]: {
    uuid: string;
  };
}[T];

export async function sendWebhook<T extends WebhookAction>(action: T, data: WebhookActionType<T>) {
  if (!WEBHOOK_ENDPOINT) return;
  else if (!/^(https?:\/\/[^\s,]+)(?:,(https?:\/\/[^\s,]+))*$/.test(WEBHOOK_ENDPOINT)) {
    logger.warn('webhook endpoint is invalid');
    return;
  }

  const webhookFutures = [];

  for (const webhook of WEBHOOK_ENDPOINT.split(',')) {
    webhookFutures.push(
      (async () => {
        let retries = 0;
        while (retries < 3) {
          try {
            const response = await fetch(webhook, {
              method: 'POST',
              headers: {
                'Content-Type': 'application/json',
                'x-webhook-action': action
              },
              body: JSON.stringify(data)
            });

            if (response.status === 200) break;
          } catch (e) {
            logger.warn(
              {
                retry: retries + 1,
                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                // @ts-ignore
                error: e.message
              },
              'error while sending webhook'
            );
          }

          retries++;
          await sleepSeconds(60);
        }
      })()
    );
  }

  await Promise.all(webhookFutures);
}
