import sendgridClient from '@sendgrid/client';
import { ClientRequest as SendgridClientRequest } from '@sendgrid/client/src/request';
import { ClientResponse as SendgridClientResponse } from '@sendgrid/client/src/response';
import { EmailData } from '@sendgrid/helpers/classes/email-address';
import mailClient, { MailDataRequired, ClientResponse as MailerClientResponse, ResponseError } from '@sendgrid/mail';

sendgridClient.setApiKey(process.env.SENDGRID_API_KEY);
mailClient.setApiKey(process.env.SENDGRID_API_KEY);

export const isEmailable = (email?: string | null) => email && !email.endsWith('@musehub.wavtool.com');

const send: (typeof mailClient)['send'] = async (
  data: MailDataRequired | MailDataRequired[],
  isMultiple?: boolean,
  cb?: (err: Error | ResponseError, result: [MailerClientResponse, {}]) => void
): Promise<[MailerClientResponse, {}]> => {
  return await mailClient.send(data, isMultiple, cb);
};

const getEmail = (emailData: EmailData): string => {
  if (emailData instanceof String) {
    return emailData as string;
  }
  return (emailData as { name?: string; email: string }).email;
};

export const sendIfAllRecipientsEmailable = async (
  data: MailDataRequired | MailDataRequired[],
  isMultiple?: boolean,
  cb?: (err: Error | ResponseError, result: [MailerClientResponse, {}]) => void
) => {
  const recipients: string[] = [];

  try {
    const handleTo = (to: EmailData | EmailData[]) => {
      if (Array.isArray(to)) {
        to.forEach((t) => recipients.push(getEmail(t)));
      } else {
        recipients.push(getEmail(to));
      }
    };

    const handleRecipientFields = (p: {
      to?: EmailData | EmailData[];
      cc?: EmailData | EmailData[];
      bcc?: EmailData | EmailData[];
    }) => {
      if (p.to) handleTo(p.to);
      if (p.cc) handleTo(p.cc);
      if (p.bcc) handleTo(p.bcc);
    };

    if (Array.isArray(data)) {
      data.forEach((d) => {
        d.personalizations?.forEach(handleRecipientFields);
        handleRecipientFields(d);
      });
    } else {
      data.personalizations?.forEach(handleRecipientFields);
      handleRecipientFields(data);
    }
  } catch (e) {
    console.log(data);
    console.error('Error enumerating recipient emails:', e);
    return null;
  }

  if (recipients.every(isEmailable)) {
    return await send(data, isMultiple, cb);
  } else {
    console.log('Not all recipients are emailable. Not sending.', recipients);
  }

  return null;
};

export const emailSenderAPICall = async (
  data: SendgridClientRequest,
  cb?: (err: ResponseError, response: [SendgridClientResponse, any]) => void
): Promise<[SendgridClientResponse, any]> => {
  return sendgridClient.request(data, cb);
};
