#!/usr/bin/python3

import hmac
import hashlib
import os
import sys

sys.path.insert(0, "/usr/local/mgr5/lib/python")
from billmgr.exception import XmlException
import billmgr.logger as logging
from billmgr.modules.paymentcgi import InputContentType, PaymentCgi, PaymentCgiType, run_cgi
from billmgr import payment

from revolut.api import WebhookEvent


logging.init_logging('revolutresult')
logger = logging.get_logger('revolutresult')


class RevolutResultCgi(PaymentCgi):
    def __init__(self):
        super().__init__()

    def cgi_type(self) -> PaymentCgiType:
        return PaymentCgiType.Payment

    @property
    def input_content_type(self) -> InputContentType:
        return InputContentType.Json

    def elid(self) -> str:
        return self.input['merchant_order_ext_ref']

    def process(self):
        self.check_signature()

        external_id = self.payment_params['externalid']
        if self.input['order_id'] != external_id:
            raise XmlException('revolut_webhook_invalid_order_id')

        event = WebhookEvent(self.input['event'])
        if event == WebhookEvent.OrderCompleted:
            payment.set_paid(int(self.elid()), external_id)
        elif event == WebhookEvent.OrderPaymentDeclined:
            payment.set_canceled(int(self.elid()), external_id)
        elif event == WebhookEvent.OrderPaymentFailed:
            payment.set_canceled(int(self.elid()), external_id)
        elif event == WebhookEvent.OrderCancelled:
            payment.set_canceled(int(self.elid()), external_id)
        else:
            logger.info(f'event {event.value} ignored')

    def check_signature(self):
        def compute_signature(raw_input: str, timestamp: str, signing_secret: str) -> str:
            payload_to_sign = 'v1.' + str(timestamp) + '.' + raw_input
            return 'v1=' + hmac.new(
                bytes(signing_secret , 'utf-8'),
                msg=bytes(payload_to_sign , 'utf-8'),
                digestmod=hashlib.sha256
            ).hexdigest()

        timestamp = os.environ['HTTP_REVOLUT_REQUEST_TIMESTAMP']
        signature = os.environ['HTTP_REVOLUT_SIGNATURE']
        computed_signature = compute_signature(
            self.raw_input,
            timestamp,
            self.paymethod_params['webhook_signing_secret']
        )
        if signature != computed_signature:
            raise XmlException('revolut_webhook_invalid_signature')


if __name__ == '__main__':
    run_cgi(RevolutResultCgi)
