## $Id: browser.py 14759 2017-08-03 09:09:54Z henrik $
##
## Copyright (C) 2017 Uli Fouquet & Henrik Bettermann
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
import grok
import hashlib
from datetime import datetime, timedelta
from zope.component import getUtility, queryUtility
from zope.security import checkPermission
from waeup.kofa.interfaces import IKofaUtils
from waeup.kofa.utils.helpers import to_timezone
from waeup.kofa.browser.layout import UtilityView, KofaPage
from waeup.kofa.browser.viewlets import ManageActionButton
from waeup.kofa.applicants.browser import OnlinePaymentDisplayFormPage as OPDPApplicant
#from kofacustom.nigeria.remita.helpers import (
#    get_JSON_POST_response, query_remita, write_payments_log)
from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment
from kofacustom.nigeria.interfaces import MessageFactory as _
from kofacustom.nigeria.paypal import module_activated, Amount, PurchaseUnit
from kofacustom.nigeria.paypal.interfaces import IPaypalConfig
from kofacustom.nigeria.paypal.rest import create_order, capture_order


# grok.templatedir('browser_templates')


# Buttons


class PaypalActionButtonApplicant(ManageActionButton):
    grok.order(1)
    grok.context(INigeriaOnlinePayment)
    grok.view(OPDPApplicant)
    grok.require('waeup.payApplicant')
    icon = 'actionicon_paypal.png'
    text = _('Pay via Paypal')
    target = 'goto_paypal'

    @property
    def target_url(self):
        # import pdb; pdb.set_trace()
        if not module_activated(
            self.context.__parent__.__parent__.year, self.context):
            return ''
        if self.context.p_state != 'unpaid':
            return ''
        return self.view.url(self.view.context, self.target)


class PaypalRequestPaymentStatusActionButtonApplicant(ManageActionButton):
    grok.order(2)
    grok.context(INigeriaOnlinePayment)
    grok.view(OPDPApplicant)
    grok.require('waeup.payApplicant')
    icon = 'actionicon_call.png'
    text = _('Requery Paypal Payment Status')
    target = 'capture_paypal_payment'

    @property
    def target_url(self):
        if not module_activated(
            self.context.__parent__.__parent__.year, self.context):
            return ''
        if self.context.p_state in ('paid', 'waived', 'scholarship'):
            return ''
        return self.view.url(self.view.context, self.target)


# Webservice request views


class PaypalRequestPaymentStatusPageApplicant(UtilityView, grok.View):
    """ Capture order created before
    """
    grok.context(INigeriaApplicantOnlinePayment)
    grok.name('capture_paypal_payment')
    grok.require('waeup.payApplicant')


    def update(self):
        if not module_activated(
            self.context.__parent__.__parent__.year, self.context):
            self.flash(_('Forbidden'), type='danger')
            self.redirect(self.url(self.context, '@@index'))
            return
        if self.context.p_state in ('paid', 'waived', 'scholarship'):
            self.flash(_('This ticket has already been paid.'), type='danger')
            return
        response = capture_order(self.context.r_pay_reference)
        if response.get("status", None) == "COMPLETED":
            self.context.p_state = u'paid'
            self.context.payment_date = datetime.utcnow()
        if not response:
            self.flash(_('Paypal Order ID not found.'), type='danger')
            return

    def render(self):
        self.redirect(self.url(self.context, '@@index'))
        return


# Forwarding pages

class PaypalPageApplicant(KofaPage):
    """ Create Paypal Order (and send user to paypal)
    """
    grok.context(INigeriaApplicantOnlinePayment)
    grok.name('goto_paypal')
    grok.require('waeup.payApplicant')
    label = _('Pay via Paypal')
    submit_button = _('Pay now')

    # Nigerian Naira would be "NGN" but is not supported with
    # most paypal accounts
    currency_code = 'USD'

    @property
    def action(self):
        return self.context.r_payment_link

    def create_paypal_order(self, currency_code):
        if self.context.r_pay_reference or self.context.p_state == 'paid':
            return _("Payment ticket can't be re-sent to Paypal.")
        if self.context.r_company and self.context.r_company != 'paypal':
            return _("Payment ticket has been used for another payment gateway.")
        now = datetime.utcnow()
        if self.context.creation_date.tzinfo is not None:
            # That's bad. Please store timezone-naive datetimes only!
            now = self.context.creation_date.tzinfo.localize(now)
        time_delta = now - self.context.creation_date
        if time_delta.days > 7:
            return _("This payment ticket is too old. Please create a new ticket.")
        # The success url...
        self.responseurl = self.url(self.context, 'capture_paypal_payment')
        amount = Amount(value=self.context.amount_auth, currency_code=self.currency_code)
        purchase_units = [
                PurchaseUnit(description=self.context.p_id, amount=amount)
                ]
        order_id, payment_link, request_id, data = create_order(
                purchase_units,
                self.responseurl,         # success/authorized url
                self.url(self.context),   # cancel/failed url
                notify_url="https://h9.waeup.org/ipn"
                )
        if not order_id:  # an error happened...
            err_msg = " ".join([x["description"] for x in data["details"]])
            return _("Paypal order failed: %s") % err_msg
        self.context.r_payment_link = payment_link
        self.context.r_pay_reference = order_id
        self.context.r_company = u'paypal'
        self.customer = self.context.__parent__
        self.customer.writeLogMessage(self, "Paypal Order Created: %s" % (
            order_id))
        return

    def update(self):
        if not module_activated(
            self.context.__parent__.__parent__.year, self.context):
            self.flash(_('Forbidden'), type='danger')
            self.redirect(self.url(self.context, '@@index'))
            return
        self.paypal_error = u''
        if not self.context.r_payment_link:
            self.paypal_error = self.create_paypal_order(self.currency_code)
        if self.paypal_error:
            self.flash(error, type='danger')
            self.redirect(self.url(self.context, '@@index'))
            return
        # Payment created - it must now be
        # - authorized (by user)
        # - captured (by us, afterwards)
        if not self.context.r_company:
            self.context.r_company = u'paypal'
        return

    def render(self):
        if self.context.r_payment_link and self.context.p_state != 'paid':
            self.redirect(self.context.r_payment_link, trusted=True)
            return
        self.redirect(self.url(self.context, '@@index'))

