## $Id: studentsbrowser.py 15599 2019-09-20 13:24:59Z 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
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 kofacustom.nigeria.etranzact.helpers import (
    write_payments_log, process_response, query_history)
from kofacustom.nigeria.students.browser import NigeriaOnlinePaymentDisplayFormPage as NOPDPStudent
from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
from kofacustom.nigeria.students.interfaces import INigeriaStudentOnlinePayment
from kofacustom.nigeria.interfaces import MessageFactory as _

from kofacustom.nigeria.etranzact.tests import (
    TERMINAL_ID, HOST, HTTPS, SECRET_KEY, LOGO_URL, GATEWAY_AMT)

grok.templatedir('browser_templates')

def webconnect_module_activated(session, payment):
    if payment.r_company and payment.r_company != 'etranzact':
        return False
    try:
        return getattr(grok.getSite()['configuration'][str(session)],
            'etranzact_webconnect_enabled', False)
    except KeyError:
        session = datetime.now().year
        try:
            return getattr(grok.getSite()['configuration'][str(session)],
                'etranzact_webconnect_enabled', False)
        except KeyError:
            return False

class EtranzactActionButtonStudent(ManageActionButton):
    grok.order(8)
    grok.context(INigeriaOnlinePayment)
    grok.view(NOPDPStudent)
    grok.require('waeup.payStudent')
    icon = 'actionicon_pay.png'
    text = _('Pay via Etranzact WebConnect')
    target = 'goto_etranzact'

    @property
    def target_url(self):
        if not webconnect_module_activated(
            self.context.student.current_session, self.context):
            return ''
        if self.context.p_state != 'unpaid':
            return ''
        return self.view.url(self.view.context, self.target)

class EtranzactRequeryActionButtonStudent(ManageActionButton):
    grok.order(9)
    grok.context(INigeriaOnlinePayment)
    grok.view(NOPDPStudent)
    grok.require('waeup.payStudent')
    icon = 'actionicon_call.png'
    text = _('Requery Etranzact WebConnect History')
    target = 'requery_history'

    @property
    def target_url(self):
        if not webconnect_module_activated(
            self.context.student.current_session, self.context):
            return ''
        if self.context.p_state in ('paid', 'waived', 'scholarship', 'failed'):
            return ''
        return self.view.url(self.view.context, self.target)

class EtranzactPageStudent(KofaPage):
    """ View which sends a POST request to the Etranzact payment gateway.
    """
    grok.context(INigeriaStudentOnlinePayment)
    grok.name('goto_etranzact')
    grok.template('goto_etranzact')
    grok.require('waeup.payStudent')
    label = _('Pay via Etranzact')
    submit_button = _('Pay now')

    host = HOST
    https = HTTPS
    secret_key = SECRET_KEY
    terminal_id = TERMINAL_ID
    logo_url = LOGO_URL
    gateway_amt = GATEWAY_AMT

    @property
    def action(self):
        if self.https:
            return 'https://' + self.host + '/webconnect/v3/caller.jsp'
        return 'http://' + self.host + '/webconnect/v3/caller.jsp'

    def init_update(self):
        if self.context.p_state == 'paid':
            return _("Payment ticket can't be re-sent to Etranzact.")
        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.")
        # In contrast to the procedure in the Remita and Interswitch modules,
        # we do not call requery_history but receive and evaluate
        # the response form from Etranzact directly. This is possible
        # because Etranzact provides the FINAL_CHECKSUM hash value
        # which authenticates the response.
        self.responseurl = self.url(self.context, 'receive_etranzact')
        self.transaction_id = self.context.p_id
        self.description = "%s (%s)" % (
            self.context.p_category, self.context.p_item)
        hashargs = 	self.amount + self.terminal_id + self.transaction_id \
            + self.responseurl + self.secret_key
        self.hashvalue = hashlib.md5(hashargs).hexdigest()
        self.customer = self.context.student
        return

    def update(self):
        if not webconnect_module_activated(
            self.context.student.current_session, self.context):
            self.flash(_('Forbidden'), type='danger')
            self.redirect(self.url(self.context, '@@index'))
            return
        # Already now it becomes an Etranzact payment. We set the net amount
        # and add the gateway amount.
        if not self.context.r_company:
            self.context.net_amt = self.context.amount_auth
            self.context.amount_auth += self.gateway_amt
            self.context.gateway_amt = self.gateway_amt
            self.context.r_company = u'etranzact'
        self.amount = "%.1f" % self.context.amount_auth
        error = self.init_update()
        if error:
            self.flash(error, type='danger')
            self.redirect(self.url(self.context, '@@index'))
            return
        return

class EtranzactReceiveResponseStudent(NOPDPStudent):
    """ View that receives the response from eTrantact payment gateway.
    """
    grok.name('receive_etranzact')

    secret_key = SECRET_KEY
    terminal_id = TERMINAL_ID

    def update(self):
        super(EtranzactReceiveResponseStudent, self).update()
        if not webconnect_module_activated(
            self.context.student.current_session, self.context):
            self.flash(_('Forbidden'), type='danger')
            self.redirect(self.url(self.context, '@@index'))
            return
        student = self.context.student
        form = self.request.form
        verify = False
        if self.context.p_state == 'paid':
            verify = True
        success, msg, log = process_response(self.context, form, self, verify)
        student.writeLogMessage(self, log)
        if not success:
            self.flash(msg, type='danger')
            return
        write_payments_log(student.student_id, self.context)
        flashtype, msg, log = self.context.doAfterStudentPayment()
        if log is not None:
            student.writeLogMessage(self, log)
        self.flash(msg, type=flashtype)
        return

class EtranzactRequestPaymentStatusPageStudent(UtilityView, grok.View):
    """ Request webservice view for the Etranzact gateway.
    """
    grok.context(INigeriaStudentOnlinePayment)
    grok.name('requery_history')
    grok.require('waeup.payStudent')

    host = HOST
    https = HTTPS
    secret_key = SECRET_KEY
    terminal_id = TERMINAL_ID
    logo_url = LOGO_URL

    def update(self):
        if not webconnect_module_activated(
            self.context.student.current_session, self.context):
            self.flash(_('Forbidden'), type='danger')
            self.redirect(self.url(self.context, '@@index'))
            return
        if self.context.p_state in ('paid', 'waived', 'scholarship', 'failed'):
            self.flash(_('This ticket has already been processed.'), type='danger')
            return
        student = self.context.student
        verify = False
        raw, form = query_history(self.host, self.terminal_id,
                                  self.context.p_id, self.https)
        success, msg, log = process_response(self.context, form, self, verify)
        student.writeLogMessage(self, log)
        if not success:
            self.flash(msg, type='danger')
            return
        write_payments_log(student.student_id, self.context)
        flashtype, msg, log = self.context.doAfterStudentPayment()
        if log is not None:
            student.writeLogMessage(self, log)
        self.flash(msg, type=flashtype)
        return

    def render(self):
        self.redirect(self.url(self.context))
        return
