const Promise = require('bluebird');
const paypal = require('paypal-rest-sdk');
const key = require('../../redisKey');
const ld = require('lodash');
const getPlan = require('../plan/get');
const moment = require('moment');
const billingAgreement = Promise.promisifyAll(paypal.billingAgreement, { context: paypal.billingAgreement });

function agreementExecute(message) {
  const { _config, redis, amqp } = this;
  const promise = Promise.bind(this);
  const { token, owner } = message;

  function sendRequest() {
    return billingAgreement.executeAsync(token, {}, _config.paypal).get('id');
  }

  function fetchUpdatedAgreement(id) {
    return billingAgreement.getAsync(id, _config.paypal);
  }

  function fetchPlan(agreement) {
    return redis.get(token).then((planId) => { return { planId, agreement }; });
  }

  function fetchSubscription(data) {
    const { planId, agreement } = data;
    const subscriptionName = agreement.plan.payment_definitions[0].frequency.toLowerCase();

    return getPlan.call(this, planId).then((plan) => {
      const subscription = ld.findWhere(plan.subs, { name: subscriptionName });
      return { agreement, subscription, planId };
    });
  }

  function updateMetadata(data) {
    const { subscription, agreement, planId } = data;

    const period = subscription.definition.frequency.toLowerCase();
    const nextCycle = moment().add(1, period).format();

    const path = _config.users.prefix + '.' + _config.users.postfix.updateMetadata;

    const updateRequest = {
      'username': owner,
      'audience': _config.users.audience,
      '$set': {
        nextCycle,
        agreement: agreement.id,
        plan: planId,
        models: subscription.models,
        modelPrice: subscription.price,
      },
    };

    return amqp.publishAndWait(path, updateRequest, { timeout: 5000 }).return(agreement);
  }

  function updateRedis(agreement) {
    const agreementKey = key('agreements-data', agreement.id);
    const pipeline = redis.pipeline();

    const data = {
      agreement,
      state: agreement.state,
      name: agreement.name,
      token,
      plan: agreement.plan.id,
      owner,
    };

    pipeline.hmset(agreementKey, ld.mapValues(data, JSON.stringify, JSON));
    pipeline.sadd('agreements-index', agreement.id);

    return pipeline.exec().return(agreement);
  }

  return promise
    .then(sendRequest)
    .then(fetchUpdatedAgreement)
    .then(fetchPlan)
    .then(fetchSubscription)
    .then(updateMetadata)
    .then(updateRedis);
}

module.exports = agreementExecute;

@@ -1518,17 +1518,16 @@
     
-'
 username
 ': o
@@ -1522,17 +1522,16 @@
 username
-'
 : owner,
@@ -1541,17 +1541,16 @@
     
-'
 audience
 ': _
@@ -1545,17 +1545,16 @@
 audience
-'
 : _confi
@@ -1581,14 +1581,32 @@
     
-'
+metadata: %7B%0A        
 $set
-'
 : %7B%0A
@@ -1613,16 +1613,18 @@
         
+ 
+ 
 nextCycl
@@ -1626,16 +1626,18 @@
 tCycle,%0A
+  
         
@@ -1665,24 +1665,26 @@
 id,%0A        
+  
 plan: planId
@@ -1685,16 +1685,18 @@
 planId,%0A
+  
         
@@ -1700,17 +1700,21 @@
    model
-s
+Price
 : subscr
@@ -1724,16 +1724,45 @@
 ion.
-models,%0A
+price,%0A        %7D,%0A        $incr: %7B%0A  
     
@@ -1762,37 +1762,33 @@
 %0A          model
-Price
+s
 : subscription.p
@@ -1778,37 +1778,49 @@
 s: subscription.
-price
+models,%0A        %7D
 ,%0A      %7D,%0A    %7D

Fix update metadata request