const Promise = require('bluebird');
const generatePassword = require('password-generator');
const { stringify } = require('qs');
const partial = require('lodash/partial');
const identity = require('lodash/identity');
const { InvalidOperationError } = require('common-errors');
const sendEmail = require('./send');
const generateLink = require('../../generate-backlink');
const { updatePassword } = require('../../../actions/updatePassword');
const {
  USERS_ACTION_ACTIVATE,
  USERS_ACTION_RESET,
  USERS_ACTION_PASSWORD,
  USERS_ACTION_REGISTER,
  USERS_ACTION_INVITE,
  USERS_ACTION_ORGANIZATION_INVITE,
  USERS_ACTION_ORGANIZATION_REGISTER,
  USERS_ACTION_ORGANIZATION_ADD,
} = require('../../../constants.js');

// will be replaced later
const { placeholder } = partial;

function generate(email, type, ctx = {}, opts = {}, nodemailer = {}) {
  const { config } = this;
  const { validation, server, pwdReset } = config;
  const { paths } = validation;

  // in the case of emails namespace is email where we send data to
  const { wait = false, send = false } = opts;
  const context = { ...ctx };
  const actions = {};
  const templateName = validation.templates[type] || type;

  context.lng = context.i18nLocale;

  switch (type) {
    case USERS_ACTION_ACTIVATE:
    case USERS_ACTION_RESET:
    case USERS_ACTION_INVITE:
      // generate secret
      context.qs = `?q=${context.token.secret}`;
      context.link = generateLink(server, paths[type]);
      break;
    case USERS_ACTION_ORGANIZATION_ADD:
      context.qs = `?${stringify({
        login: ctx.email,
        firstName: ctx.firstName,
        lastName: ctx.lastName,
        organizationId: ctx.organizationId,
      })}`;
      context.link = generateLink(server, paths[USERS_ACTION_ORGANIZATION_ADD]);
      break;
    case USERS_ACTION_ORGANIZATION_REGISTER:
      context.qs = `?${stringify({
        password: ctx.password,
        login: ctx.email,
        firstName: ctx.firstName,
        lastName: ctx.lastName,
        organizationId: ctx.organizationId,
      })}`;
      context.link = generateLink(server, paths[USERS_ACTION_ORGANIZATION_REGISTER]);
      break;
    case USERS_ACTION_ORGANIZATION_INVITE:
      context.qs = `?${stringify({
        q: context.token.secret,
        organizationId: ctx.organizationId,
        username: ctx.email,
        firstName: ctx.firstName,
        lastName: ctx.lastName,
        skipPassword: ctx.skipPassword,
      })}`;
      context.link = generateLink(server, paths[USERS_ACTION_ORGANIZATION_INVITE]);
      break;

    case USERS_ACTION_PASSWORD:
    case USERS_ACTION_REGISTER:
      context.password = generatePassword(pwdReset.length, pwdReset.memorable);
      context.login = email;
      break;

    default:
      throw new InvalidOperationError(`${type} action is not supported`);
  }

  // in case we need to setup a new password
  if (type === USERS_ACTION_PASSWORD) {
    actions.updatePassword = updatePassword.call(this, email, context.password);
  }

  this.log.info('Generated mail %s', templateName);

  return Promise
    .props({
      ...actions,
      type,
      email,
      context,
      nodemailer,
      templateName,
    })
    .bind(this)
    .then((output) => (send ? [output, wait] : [output]))
    .spread(send ? sendEmail : identity);
}

// main export
module.exports = exports = generate;

// short-hand methods
exports.newPassword = partial(generate, placeholder, USERS_ACTION_PASSWORD, {}, { send: true });
exports.register = partial(generate, placeholder, USERS_ACTION_REGISTER, placeholder, placeholder);

// these should simply generate an email
// as they are likely to be used from withing createChallenge or require custom context
exports.activation = partial(generate, placeholder, USERS_ACTION_ACTIVATE);
exports.resetPassword = partial(generate, placeholder, USERS_ACTION_RESET);
exports.invite = partial(generate, placeholder, USERS_ACTION_INVITE);

@@ -1375,32 +1375,89 @@
 = %60?
-q=$%7Bcontext.token.secret
+$%7Bstringify(%7B%0A        q: context.token.secret,%0A        lng: context.lng,%0A      %7D)
 %7D%60;%0A
@@ -1728,32 +1728,58 @@
 organizationId,%0A
+        lng: context.lng,%0A
       %7D)%7D%60;%0A    
@@ -2112,24 +2112,50 @@
 nizationId,%0A
+        lng: context.lng,%0A
       %7D)%7D%60;%0A
@@ -2495,32 +2495,32 @@
 : ctx.lastName,%0A
-
         skipPass
@@ -2539,24 +2539,50 @@
 ipPassword,%0A
+        lng: context.lng,%0A
       %7D)%7D%60;%0A

add lng parameter to email links