// newsletter/job/transmit.js
// Copyright (C) 2022 DTP Technologies, LLC
// License: Apache-2.0

'use strict';

const path = require('path');

const mongoose = require('mongoose');

const User = mongoose.model('User');
const NewsletterRecipient = mongoose.model('NewsletterRecipient');

const { SiteWorkerProcess } = require(path.join(__dirname, '..', '..', '..', '..', 'lib', 'site-lib'));

class NewsletterTransmitJob extends SiteWorkerProcess {

  static get COMPONENT ( ) {
    return {
      name: 'newsletterTransmitJob',
      slug: 'newsletter-transmit-job',
    };
  }

  constructor (worker) {
    super(worker, NewsletterTransmitJob.COMPONENT);
  }

  async start ( ) {
    await super.start();

    this.queue = await this.getJobQueue('newsletter', this.dtp.config.jobQueues.newsletter);

    this.log.info('registering job processor', { queue: this.queue.name, name: 'transmit' });
    this.queue.process('transmit', this.processTransmit.bind(this));
  }

  async stop ( ) {
    await super.stop();
  }

  async processTransmit (job) {
    const { newsletterId } = job.data;
    this.log.info('newsletter email job received', { id: job.id, newsletterId });

    try {
      /*
       * Transmit first to all local user accounts with verified email who've
       * opted in for receiving marketing email.
       */
      await User
        .find({
          'flags.isEmailVerified': true,
          'optIn.marketing': true,
        })
        .select('email displayName username username_lc')
        .lean()
        .cursor()
        .eachAsync(async (user) => {
          try {
            const jobData = {
              newsletterId: newsletterId,
              recipient: user.email,
              recipientName: user.displayName || user.username,
            };
            const jobOptions = { attempts: 3 };
            await this.queue.add('email-send', jobData, jobOptions);
          } catch (error) {
            this.log.error('failed to create newsletter email job', { error });
          }
        }, { parallel: 4 });

      /*
       * Transmit to all newsletter recipients on file who've joined through the
       * widget on the site w/o signing up for an account.
       */
      await NewsletterRecipient
        .find({ 'flags.isVerified': true, 'flags.isOptIn': true, 'flags.isRejected': false })
        .lean()
        .cursor()
        .eachAsync(async (recipient) => {
          try {
            const jobData = {
              newsletterId: newsletterId,
              recipient: recipient.address,
            };
            const jobOptions = { attempts: 3 };
            await this.queue.add('email-send', jobData, jobOptions);
          } catch (error) {
            this.log.error('failed to create newsletter email job', { error });
          }
        }, { parallel: 4 });
    } catch (error) {
      this.log.error('failed to send newsletter', { newsletterId, error });
      throw error;
    }
  }
}

module.exports = NewsletterTransmitJob;