import models from '../../models';
import roles from '../../constants/roles';
import * as libpayments from '../../lib/payments';
import * as libtransactions from '../../lib/transactions';
import { TransactionTypes, OC_FEE_PERCENT } from '../../constants/transactions';

/** Get the balance of a prepaid credit card
 *
 * When a card is created by a host (by adding funds to an
 * organization for example) the card is created with an initial
 * balance. This function subtracts the amount from transactions made
 * with this card from the initial balance.
 *
 * @param {models.PaymentMethod} paymentMethod is the instance of the
 *  prepaid credit card payment method.
 * @return {Object} with amount & currency from the payment method.
 */
async function getBalance(paymentMethod) {
  if (!libpayments.isProvider('opencollective.prepaid', paymentMethod)) {
    throw new Error(`Expected opencollective.prepaid but got ${paymentMethod.service}.${paymentMethod.type}`);
  }
  /* Result will be negative (We're looking for DEBIT transactions) */
  const spent = await libtransactions.sum({
    PaymentMethodId: paymentMethod.id,
    currency: paymentMethod.currency,
    type: 'DEBIT',
  });
  return {
    amount: paymentMethod.initialBalance + spent,
    currency: paymentMethod.currency,
  };
}

/** Process a pre paid card order
 *
 * @param {models.Order} order The order instance to be processed.
 * @return {models.Transaction} As any other payment method, after
 *  processing Giftcard orders, the transaction generated from it is
 *  returned.
 */
async function processOrder(order) {
  const user = order.createdByUser;
  const { paymentMethod: { data } } = order;

  // Making sure the paymentMethod has the information we need to
  // process a prepaid card
  if (!order.paymentMethod.customerId)
    throw new Error('Prepaid method must have a value for `customerId`');
  if (!data || !data.HostCollectiveId)
    throw new Error('Prepaid method must have a value for `data.HostCollectiveId`');

  // Check if the prepaid card was created for the collective making
  // the donation
  const fromCollective = await models.Collective.findById(order.FromCollectiveId);
  if (order.paymentMethod.customerId !== fromCollective.slug)
    throw new Error('Prepaid method can only be used by the organization that received it');

  // Check that target Collective's Host is same as gift card issuer
  const hostCollective = await order.collective.getHostCollective();
  if (hostCollective.id !== data.HostCollectiveId)
    throw new Error('Prepaid method can only be used in collectives from the same host');

  // Use the above payment method to donate to Collective
  const hostFeeInHostCurrency = libpayments.calcFee(
    order.totalAmount,
    order.collective.hostFeePercent);
  const platformFeeInHostCurrency = libpayments.calcFee(
    order.totalAmount, OC_FEE_PERCENT);
  const transactions = await models.Transaction.createFromPayload({
    CreatedByUserId: user.id,
    FromCollectiveId: order.FromCollectiveId,
    CollectiveId: order.CollectiveId,
    PaymentMethodId: order.paymentMethod.id,
    transaction: {
      type: TransactionTypes.CREDIT,
      OrderId: order.id,
      amount: order.totalAmount,
      amountInHostCurrency: order.totalAmount,
      currency: order.currency,
      hostCurrency: order.currency,
      hostCurrencyFxRate: 1,
      hostFeeInHostCurrency,
      platformFeeInHostCurrency,
      paymentProcessorFeeInHostCurrency: 0,
      description: order.description
    }
  });

  // add roles
  await order.collective.findOrAddUserWithRole({ id: user.id, CollectiveId: order.fromCollective.id}, roles.BACKER, {
    CreatedByUserId: user.id, TierId: order.TierId,
  });

  // Mark order row as processed
  await order.update({ processedAt: new Date() });

  // Mark paymentMethod as confirmed
  order.paymentMethod.update({ confirmedAt: new Date() });

  return transactions;
}

/* Expected API of a Payment Method Type */
export default {
  features: {
    recurring: true,
    waitToCharge: false
  },
  getBalance,
  processOrder,
};

@@ -1666,16 +1666,33 @@
  order;%0A
+  console.log(0);
 %0A  // Ma
@@ -2247,17 +2247,224 @@
 ve.slug)
+ %7B
 %0A
+    //if the PM has the CollectiveId setup, it's supposed to be the same as the FromCollectiveId%0A    if (!order.paymentMethod.CollectiveId %7C%7C order.paymentMethod.CollectiveId !== order.FromCollectiveId)%0A  
     thro
@@ -2544,24 +2544,27 @@
 eived it');%0A
+  %7D
 %0A  // Check 

check not only the slug, but also if PM.ColletiveId matches order.FromCollective.id so it won't throw error