"use strict";
const { STAGING } = require("../config/appConfig");
const {
  matchRealEstates,
  matchSearchRequest
} = require("../services/searchMatchService");
const {
  generateNotificationEmail,
  generateNewSearchRequestEmail,
  generateEmailSubject,
  generateCheckUpEmail
} = require("../helpers/emailContentGenerator");
const {
  findNotNotifiedMatches,
  findAllRequestsForCheckUp,
  findRealEstatesForSearchRequest
} = require("../helpers/db/searchRequestMatch");
const { sendEmail } = require("../services/emailService");

const notifyForNewRealEstates = async newRealEstates => {
  const matches = await matchRealEstates(newRealEstates);
  await notifyMatches(matches);
};

const notifyForNewSearchRequest = async searchRequest => {
  const matches = await matchSearchRequest(searchRequest);

  const searchRequestId = searchRequest.id;
  const matchingRealEstates = matches[searchRequestId].realEstates;
  const stagingTag = STAGING ? "[STAGING] " : "";
  const emailContent = generateNewSearchRequestEmail(
    searchRequest,
    matchingRealEstates
  );
  const { email } = searchRequest;
  await sendEmail(
    email,
    `${stagingTag} Kivi - novi zahtjev za pretragu`,
    emailContent
  );
};

const notifyMatches = async (matches, dailyNotification = false) => {
  const searchRequestsToNotify = Object.keys(matches);

  const asyncSendEmailActions = [];
  for (const id of searchRequestsToNotify) {
    const { searchRequest, notifyNow } = matches[id];
    const { email, subscribed } = searchRequest;
    if (notifyNow && subscribed) {
      const allMatchingRealEstates = matches[id].realEstates || [];

      //Variable allMatchingRealEstates are real estates that are "new" on the market
      //the ones that we notify user in this moment, not all that already exists in db
      //New variable allRealEstates are all real estates that exists in db for search req
      const allRealEstates = await findRealEstatesForSearchRequest(id);
      const noAllRealEstates = allRealEstates.length;

      if (allMatchingRealEstates.length > 0) {
        const emailContent = generateNotificationEmail(
          allMatchingRealEstates,
          id,
          noAllRealEstates,
          dailyNotification
        );
        const emailSubject = generateEmailSubject(
          allMatchingRealEstates.length,
          allMatchingRealEstates[0].title
        );

        const sendEmailPromise = sendEmail(email, emailSubject, emailContent);
        asyncSendEmailActions.push(sendEmailPromise);
        sendEmailPromise.catch(err =>
          console.log("[Email Sending Failed]", err)
        );
      }
    }
  }

  await Promise.all(asyncSendEmailActions);
};

const notifyRequestsWithDailyOption = async () => {
  const notNotifiedSearchRequestMatches = await findNotNotifiedMatches();

  const matches = {};

  for (const searchRequestMatch of notNotifiedSearchRequestMatches) {
    const { searchRequests, realEstates } = searchRequestMatch;

    if (!Array.isArray(searchRequests) || searchRequests.length !== 1) {
      // Something is wrong with this match
      // (search request not found for specified search request id)
      // OR
      // there are multiple search requests with the same ID (this should never be the case !
      // TODO: Maybe if association is defined better, this will be automatically only one object instead of array
      continue;
    }

    if (!Array.isArray(realEstates) || realEstates.length !== 1) {
      // Something is wrong with this match
      // (real estate not found for specified real estate id)
      // OR
      // there are multiple real estates with the same ID (this should never be the case !
      // TODO: Maybe if association is defined better, this will be automatically only one object instead of array
      continue;
    }

    const searchRequest = searchRequests[0];
    const realEstate = realEstates[0];
    const searchRequestId = searchRequest.id;

    if (!matches[searchRequestId]) {
      matches[searchRequestId] = {
        searchRequest,
        realEstates: [],
        notifyNow: true
      };
    }

    matches[searchRequestId].realEstates.push(realEstate);

    searchRequestMatch.notified = true;
    searchRequestMatch.save();
  }

  await notifyMatches(matches, true);
};

const checkUpNotify = async () => {
  const searchRequestsForCheckUp = await findAllRequestsForCheckUp();

  const asyncSendEmailActions = [];

  for (const searchRequest of searchRequestsForCheckUp) {
    const { email } = searchRequest.dataValues;
    const emailSubject = `Kivi: Mi tražimo nekretnine za vas!`;
    const emailContent = generateCheckUpEmail(searchRequest.dataValues);

    const sendEmailPromise = sendEmail(email, emailSubject, emailContent);
    asyncSendEmailActions.push(sendEmailPromise);
    sendEmailPromise.catch(err => console.log("[Email Sending Failed]", err));
  }
  await Promise.all(asyncSendEmailActions);
};

module.exports = {
  notifyForNewRealEstates,
  notifyForNewSearchRequest,
  notifyRequestsWithDailyOption,
  checkUpNotify
};
