const {Controller} = require('bak')
const {User} = require('../models')
const Boom = require('boom')
const Config = require('config');

const ZarinpalCheckout = require('zarinpal-checkout');
const zarinpal = ZarinpalCheckout.create(Config.get('zarinpal.merchant_id'), false);
// const baseUrl = Config.get('zarinpal.base_url')
const baseUrl = 'https://ceit93.ir/'


class PaymentController extends Controller {

  init() {
    this.post('/payment/pay', this.pay)
    this.post('/payment/add', this.add)
    this.get('/payment/check/add', this.checkAdd)
    this.get('/payment/check', this.check)
    this.get('/payment/status', this.status)
  }

  async checkAdd(request, h) {
    let params = request.query;
    let user = await User.findById(request.user._id);
    let transaction = {};
    let transactionID = 0;
    user.addFamily.forEach((e,i) => {
      if (params.Authority === e.Authority) {
        transaction = e;
        transactionID = i;
      }
    });
    if (transaction === {})
      return Boom.badRequest('درخواست بدی فرستادی :دی');
    else {
      try {
        if (!params.Authority)
          return Boom.badRequest('درخواست بدی فرستادی :دی');
        // check user send him/her self authority as query string
        if (params.Status === 'OK') {

            // if user payed the cost => no need to verify
            if (transaction.status) {
              return this.getUserRegister(user);
            }
            let verify = await zarinpal.PaymentVerification({
              Amount: (transaction.newFamily - user.registration.family) * 30 * 1000, // In Tomans
              Authority: params.Authority,
            });
            if (verify.status === 100) {
              user.addFamily[transactionID].status = true;
              console.log(user.addFamily[transactionID]);
              user.registration.cost += (transaction.newFamily - user.registration.family) * 30;
              user.registration.family = transaction.newFamily;
              await user.save();
              return this.getUserRegister(user)
            }
        }
        else if (params.Status === 'NOK') {
          let verify = await zarinpal.PaymentVerification({
            Amount: (transaction.newFamily - user.registration.family) * 30 * 1000, // In Tomans
            Authority: params.Authority,
          });
          if (verify.status === -21)
            throw Boom.paymentRequired('هیچ نوع عملیاتی برای این تراکنش یافت نشد.:(')
          else if (verify.status === 100)
            return this.getUserRegister(user)
          else
            throw Boom.paymentRequired('با پشتیبانی تماس بگیرید. عارف حسینی کیا : 09024855528')

        } else { // Bad Request

        }

        throw Boom.paymentRequired('لطفا از قسمت ثبت نام جشن هزینه خود را پرداخت کنید.')
      } catch (e) {
        return e;
      }
    }


  }

  /**
   * Checks that user payed the cost or not
   * @param request
   * @param h
   * @returns {Promise<*>}
   */
  async check(request, h) {
    let params = request.query;
    let user = await User.findById(request.user._id);
    try {
      if (!params.Authority)
        return Boom.badRequest('درخواست بدی فرستادی :دی');
      // check user send him/her self authority as query string
      if (params.Status === 'OK') {

        // checks loggedIn user payed him/her self cost
        if (user.registration.Authority === params.Authority) {
          // if user payed the cost => no need to verify
          if (user.registration.status && this.isPayedCorrect(user.registration)) {
            return this.getUserRegister(user);
          }
          let verify = await zarinpal.PaymentVerification({
            Amount: user.registration.cost * 1000, // In Tomans
            Authority: params.Authority,
          });
          if (verify.status === 100 && this.isPayedCorrect(user.registration)) {
            user.registration.status = true;
            await user.save();
            return this.getUserRegister(user)
          }
        }
      }
      else if (params.Status === 'NOK') {
        let verify = await zarinpal.PaymentVerification({
          Amount: user.registration.cost * 1000, // In Tomans
          Authority: params.Authority,
        });
        if (verify.status === -21)
          throw Boom.paymentRequired('هیچ نوع عملیاتی برای این تراکنش یافت نشد.:(')
        else if (verify.status === 100)
          return this.getUserRegister(user)
        else
          throw Boom.paymentRequired('با پشتیبانی تماس بگیرید. عارف حسینی کیا : 09024855528')

      } else { // Bad Request

      }

      throw Boom.paymentRequired('لطفا از قسمت ثبت نام جشن هزینه خود را پرداخت کنید.')
    } catch (e) {
      return e;
    }


  }

  /**
   * User requests to pay the cost and we return gateway url to him
   * @param request
   * @param h
   * @returns {Promise<{gateway: {url: *}}>}
   */
  async pay(request, h) {
    let payload = request.payload;
    // get user
    let user = await User.findById(request.user._id)
    try {
      // first try to get gateway from zarinpal
      let gateway = await zarinpal.PaymentRequest({
        Amount: this.isPayedCorrect({
          selfPayed: user.registration.selfPayed,
          cost: payload.cost,
          family: payload.family
        }) ? payload.cost * 1000 : 0,
        CallbackURL: `${baseUrl}/register/added`,
        Description: 'پرداخت هزینه جشن فارغ التحصیلی 1393',
        Email: payload.email,
        Mobile: payload.phone
      });
      payload.Authority = gateway.authority;

      let keys = Object.keys(payload);

      keys.forEach((e) => {
        user.registration[e] = payload[e]
      });

      await user.save();

      return {
        gateway: {
          url: gateway.url
        }
      }
    } catch (e) {
      console.log(e);
    }
  }

  /**
   * User requests to edit his family and we return gateway url to him
   * @param request
   * @param h
   * @returns {Promise<{gateway: {url: *}}>}
   */
  async add(request, h) {
    let newFamily = request.payload.newFamily;
    // get user
    let user = await User.findById(request.user._id)
    if (user.registration.status) {
      if (user.registration.family === newFamily)
        return Boom.paymentRequired('نفراتی اضافه نشده اند.')
      else {
        try {
          // first try to get gateway from zarinpal
          let gateway = await zarinpal.PaymentRequest({
            Amount: (newFamily - user.registration.family) * 30 * 1000,
            CallbackURL: `${baseUrl}/register/added`,
            Description: 'اضافه کردن مهمان جشن فارغ التحصیلی 1393',
            Email: user.registration.email,
            Mobile: user.registration.phone
          });

          user.addFamily.push({
            Authority: gateway.authority,
            newFamily: newFamily,
            date: new Date(),
            status: false
          });

          await user.save();

          return {
            gateway: {
              url: gateway.url
            }
          }
        } catch (e) {
          console.log(e);
        }
      }

    } else {
      throw Boom.paymentRequired('ابتدا ثبت نام کنید.')
    }

  }


  /**
   * Return payment status of user.
   * @param request
   * @param h
   * @returns {Promise<*>}
   */
  async status(request, h) {
    try {
      let user = await User.findById(request.user._id);
      if (user.registration.status)
        return {
          status: user.registration.status,
          ticket: this.getUserRegister(user)
        }
      return {
        status: user.registration.status,
        selfPayed: user.registration.selfPayed,
      }
    } catch (e) {

    }
  }

  /**
   * Checks that registration cost is correct depend on selfPayed(user),family,cost(request)
   * @param registration
   * @returns {boolean}
   */
  isPayedCorrect(registration) {
    if (registration.selfPayed)
      return registration.cost === (registration.family * 30) + 15;
    else
      return registration.cost === (registration.family) * 30 + 45;
  }

  /**
   * Return object that should be in response when the user is registered successfully
   * @param user
   * @returns {{name, email: *|email|{type, required}|{type, index, sparse, unique}, phone: *|phone|{type, required}|string, family: *|family|{type, required}, cost: *|cost|{type, required}}}
   */
  getUserRegister(user) {
    return {
      name: user.name,
      email: user.registration.email,
      phone: user.registration.phone,
      family: user.registration.family,
      cost: user.registration.cost
    }
  }

}

module.exports = PaymentController