text: const url = require('url');
  const settingsCache = require('../settings/cache');
  const config = require('../../config');
  const MembersApi = require('../../lib/members');
  const common = require('../../lib/common');
  const models = require('../../models');
  const mail = require('../mail');
  const blogIcon = require('../../lib/image/blog-icon');
  
  function createMember({name, email, password}) {
      return models.Member.add({
          name,
          email,
          password
      }).then((member) => {
          return member.toJSON();
      });
  }
  
  function updateMember(member, newData) {
      return models.Member.findOne(member, {
          require: true
      }).then(({id}) => {
          return models.Member.edit(newData, {id});
      }).then((member) => {
          return member.toJSON();
      });
  }
  
  function getMember(data, options) {
      options = options || {};
      return models.Member.findOne(data, options).then((model) => {
          if (!model) {
              return null;
          }
          return model.toJSON(options);
      });
  }
  
  function listMembers(options) {
      return models.Member.findPage(options).then((models) => {
          return {
              members: models.data.map(model => model.toJSON(options)),
              meta: models.meta
          };
      });
  }
  
  function validateMember({email, password}) {
      return models.Member.findOne({email}, {
          require: true
      }).then((member) => {
          return member.comparePassword(password).then((res) => {
              if (!res) {
                  throw new Error('Password is incorrect');
              }
              return member;
          });
      }).then((member) => {
          return member.toJSON();
      });
  }
  
  function parseMembersSettings() {
      let membersSettings = settingsCache.get('members_subscription_settings');
      if (!membersSettings) {
          membersSettings = {
              isPaid: false,
              paymentProcessors: [{
                  adapter: 'stripe',
                  config: {
                      secret_token: '',
                      public_token: '',
                      product: {
                          name: 'Ghost Subscription'
                      },
                      plans: [
                          {
                              name: 'Monthly',
                              currency: 'usd',
                              interval: 'month',
                              amount: ''
                          },
                          {
                              name: 'Yearly',
                              currency: 'usd',
                              interval: 'year',
                              amount: ''
                          }
                      ]
                  }
              }]
          };
      }
      if (!membersSettings.isPaid) {
          membersSettings.paymentProcessors = [];
      }
      return membersSettings;
  }
  
  const publicKey = settingsCache.get('members_public_key');
  const privateKey = settingsCache.get('members_private_key');
  const sessionSecret = settingsCache.get('members_session_secret');
  const passwordResetUrl = config.get('url');
  const {protocol, host} = url.parse(config.get('url'));
  const siteOrigin = `${protocol}//${host}`;
  const issuer = siteOrigin;
  const ssoOrigin = siteOrigin;
  let mailer;
  
  const membersConfig = config.get('members');
  const membersSettings = parseMembersSettings();
  
  function validateAudience({audience, origin}) {
      if (audience === origin) {
          return Promise.resolve();
      }
      if (audience === siteOrigin) {
          if (membersConfig.contentApiAccess.includes(origin)) {
              return Promise.resolve();
          }
      }
      return Promise.reject();
  }
  
  function sendEmail(member, {token}) {
      if (!(mailer instanceof mail.GhostMailer)) {
          mailer = new mail.GhostMailer();
      }
      const message = {
          to: member.email,
          subject: 'Reset password',
          html: `
          Hi ${member.name},
  
          To reset your password, click the following link and follow the instructions:
  
          ${passwordResetUrl}#reset-password?token=${token}
  
          If you didn't request a password change, just ignore this email.
          `
      };
  
      /* eslint-disable */
      // @TODO remove this
      console.log(message.html);
      /* eslint-enable */
      return mailer.send(message).catch((err) => {
          return Promise.reject(err);
      });
  }
  
  const defaultBlogTitle = settingsCache.get('title') ? settingsCache.get('title').replace(/"/g, '\\"') : 'Publication';
  const blogIconUrl = blogIcon.getIconUrl();
  const api = MembersApi({
      authConfig: {
          issuer,
          publicKey,
          privateKey,
          sessionSecret,
          ssoOrigin
      },
      paymentConfig: {
          processors: membersSettings.paymentProcessors
      },
      siteConfig: {
          title: defaultBlogTitle,
          icon: blogIconUrl
      },
      validateAudience,
      createMember,
      getMember,
      listMembers,
      validateMember,
      updateMember,
      sendEmail
  });
  
  const updateSettingFromModel = function updateSettingFromModel(settingModel) {
      if (settingModel.get('key') === 'members_subscription_settings'
              || settingModel.get('key') === 'title'
          || settingModel.get('key') === 'icon') {
          let membersSettings = parseMembersSettings();
          const defaultBlogTitle = settingsCache.get('title') ? settingsCache.get('title').replace(/"/g, '\\"') : 'Publication';
          const blogIconUrl = blogIcon.getIconUrl();
          api.reconfigureSettings({
              paymentConfig: {
                  processors: membersSettings.paymentProcessors
              },
              siteConfig: {
                  title: defaultBlogTitle,
                  icon: blogIconUrl
              }
          });
      }
  };
  
  // Bind to events to automatically keep subscription info up-to-date from settings
  common.events.on('settings.edited', updateSettingFromModel);
  
  module.exports = api;
  module.exports.publicKey = publicKey;
  module.exports.isPaymentConfigured = function () {
      let membersSettings = parseMembersSettings();
      return !!membersSettings.paymentProcessors.length;
  };