#!/usr/bin/python3
import argparse
import sys
from datetime import timedelta, datetime
from typing import Dict, List, Set
from xml.etree import ElementTree as ET


sys.path.insert(0, "/usr/local/mgr5/lib/python")

import billmgr.db
import billmgr.exception
import billmgr.logger as logging
import billmgr.session as session

# from billmgr.exception import log_backtrace

from billmgr.modules.paymethod import PaymentBehavior, PaymentTypeInfo, PaymethodModule, Feature, Param
from billmgr import payment


from payssion.api import PayssionAPI
from payssion.enums import PaymentStatus
from payssion.exceptions import InvalidResponseException


MODULE = "pmpayssion"
logging.init_logging(MODULE)
logger = logging.get_logger(MODULE)

class PayssionModule(PaymethodModule):
    def __init__(self):
        super().__init__()
        self._add_feature(Feature.REDIRECT)
        self._add_feature(Feature.REFUND)
        self._add_feature(Feature.NOT_PROFILE)
        
        self._add_callable_feature(Feature.CRSET, self.sr_set)
        self._add_callable_feature(Feature.RFSET, self.rf_set)
        self._add_callable_feature(Feature.CHECKPAY, self.check_pay)
        self._add_callable_feature(Feature.PMVALIDATE, self.pm_validate)

        self._add_param(Param.PAYMENT_SCRIPT, "/mancgi/payssionpayment")

        self._set_paymethod_payment_type("pm_id", "",
        [
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "fpx_my", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "duitnow_my", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "grabpay_my", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "boost_my", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "touchngo_my", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "qris_id", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "atm_id", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "alfamart_id", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "ovo_id", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "doku_id", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "dragonpay_ph", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "ebanking_ph", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "qr_ph", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "grabpay_ph", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "shopeepay_ph", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "pesonet_ph", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "gcash_ph", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "maya_ph", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "easypaisa_pk", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "alfa_pk", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "jazzcash_pk", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "konnect_pk", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "ebanking_za", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "creditcard_za", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "santander_ar", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "pagofacil_ar", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "rapipago_ar", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "pix_br", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "picpay_br", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "ame_br", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "boleto_br", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "pagbank_br", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bancodobrasil_br", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "itau_br", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bradesco_br", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "caixa_br", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "santander_br", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "efecty_co", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "pse_co", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "spei_mx", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "oxxo_mx", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bcp_pe", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "interbank_pe", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "pagoefectivo_pe", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "redpagos_uy", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "webpay_cl", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "enets_sg", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "paynow_sg", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "ebanking_th", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "cherrycredits", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "molpoints", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "molpointscard", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "alipay_cn", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "tenpay_cn", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "unionpay_cn", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "gash_tw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "upi_in", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "paytm_in", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "ebanking_in", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bankcard_in", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "creditcard_kr", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "ebanking_kr", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "kakaopay_kr", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "payco_kr", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "ssgpay_kr", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "samsungpay_kr", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "onecard", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "fawry_eg", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bancomer_mx", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "santander_mx", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "abitab_uy", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bancochile_cl", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "redcompra_cl", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "servipag_cl", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "santander_cl", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bbva_pe", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "boacompra", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "yamoney", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "webmoney", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "yamoneyac", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "yamoneygp", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "moneta_ru", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "alfaclick_ru", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "promsvyazbank_ru", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "faktura_ru", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "banktransfer_ru", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bankcard_tr", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "ininal_tr", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bkmexpress_tr", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "banktransfer_tr", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "paysafecard", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "sofort", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "giropay_de", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "eps_at", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bancontact_be", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "dotpay_pl", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "p24_pl", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "payu_pl", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "payu_cz", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "ideal_nl", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "multibanco_pt", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "neosurf", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "polipayment", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bitcoin", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "airtel_ke", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "mpesa_ke", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "airtel_mw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "airtel_rw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "tigo_tz", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "airtel_ug", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "airtel_zm", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "usdt", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "skrill", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "alipay_hk", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "mpay_mo", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "creditcard_tw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "payinstore_tw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "atm_tw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "postatm_tw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "aptg_tw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "fetnet_tw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "tm_tw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "cht839_tw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "chtland_tw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "chthinet_tw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "eswebatm_tw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "linepay_jp", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "rakutenpay", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "naverpay_kr", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "toss_kr", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "hipay_mn", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "akulaku_id", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "dana_id", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "linkaja_id", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "creditcard_id", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "shopeepay_id", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "promptpay_th", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "truemoney_th", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "shopeepay_th", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "kplus_th", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bpi_ph", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "instapay_ph", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "vietqr_vn", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "mada_sa", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "stcpay_sa", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "applepay_sa", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "card_kw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "applepay_kw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "card_ae", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "applepay_ae", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "card_om", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "applepay_om", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "card_qa", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "applepay_qa", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "card_bh", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "applepay_bh", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bankcard_ng", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "banktransfer_ng", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "mtn_rw", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "mtn_ug", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "mtn_ci", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "orange_ci", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "mtn_zm", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "creditcard_br", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "paycash_mx", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "creditcard_mx", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "sbp_ru", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "tbank_ru", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "card_ru", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "yoomoney_ru", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "sberpay_ru", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "payid_au", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "afterpay_us", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "trustly", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "twint_ch", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "paysera", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "payconiq", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "blik_pl", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "mybank", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "bancomatpay_it", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "satispay", False, {}),
            PaymentTypeInfo(PaymentBehavior.pbRedirect, "mbway_pt", False, {}) 
        ]
        ) 

    def _on_raise_exception(self, args: argparse.Namespace, err: billmgr.exception.XmlException):
        print(err.as_xml())

    def sr_set(self):
        pass # костыль только чтобы показывались способы оплаты на последнем шаге

    def pm_validate(self):
        logger.info("run pm_validate")

        xml = session.get_input_xml()

        is_test: bool = self.__convert_is_test_to_bool(
            xml.findtext("test", default="on"))
        api_key: str = xml.findtext("api_key", default="")
        secret_key: str = xml.findtext("secret_key", default="")

        api = PayssionAPI(api_key=api_key, secret_key=secret_key, is_test=is_test)

        if not api.is_api_ok():
            logger.info(
                "API is down; unable to create paymethod now")
            raise billmgr.exception.XmlException("payssion_api_down")

        api.is_valid_api_keys()

    def check_pay(self):
        logger.info("run checkpay")

        from_date: str = (datetime.today() - timedelta(days=10)
                          ).strftime("%Y-%m-%d")
        mgr_payments: List[billmgr.db.Record] = billmgr.db.db_query(f"""
            SELECT p.id, p.paymethodamount, p.externalid, pm.xmlparams,
            p.number, p.createdate FROM payment p
            JOIN paymethod pm ON p.paymethod = pm.id
            WHERE module = "pmpayssion"
                AND p.status = {payment.PaymentStatus.psInPay.value}
                AND createdate >= \"{from_date}\"
            ORDER BY pm.xmlparams
        """)

        if len(mgr_payments) == 0:
            logger.info("No payments in mgr database")
            return

        xml_params: Set[str] = {p.as_str("xmlparams") for p in mgr_payments}

        # payments split by xmlparams
        mgr_payments_split: Dict[str, List[billmgr.db.Record]] = {}

        # split payments by xml params
        for pay in mgr_payments:
            xml = pay.as_str("xmlparams")
            if xml not in mgr_payments_split:
                mgr_payments_split[xml] = []
            mgr_payments_split[xml].append(pay)

        # begin checking payments sorted by xml params
        for xml in xml_params:
            params = ET.fromstring(xml)
            api_key = params.findtext("api_key", default="")
            secret_key = params.findtext("secret_key", default="")
            # psw = params.findtext("password", default="")
            is_test: bool = self.__convert_is_test_to_bool(
                params.findtext("test", default="on"))

            api = PayssionAPI(api_key=api_key, secret_key=secret_key, is_test=is_test)

            # check and assign status for each payment
            for pay in mgr_payments_split[xml]:
                try:
                    logger.info("pay info:")
                    logger.info(pay)
                    order_id = pay.get("number")
                    transaction_id = pay.get("externalid")
                    payssionpay = api.get_payment_by_transaction(
                        transaction_id=transaction_id, order_id=order_id)

                    if not payssionpay:
                        logger.info(
                            f"Encountered empty list for invoice id {order_id}")
                        continue

                    logger.info("payssionpay info:")
                    logger.info(payssionpay)

                    self.__set_bill_payment_status(
                        pay.as_int("id"),
                        payssionpay,
                        api,
                        datetime.fromtimestamp(pay.as_int("created")))
                    logger.info(
                        f"payment {pay['id']} invoice_id {pay['externalid']} matched")
                except InvalidResponseException:
                    logger.error(
                        f"failed to retrieve payments for payment with externalid {order_id} "
                        f"while checking pay"
                    )

                except Exception:
                    billmgr.exception.log_backtrace()

    def rf_set(self):
        xml = session.get_input_xml()
        logger.info(f"refund xml = {ET.tostring(xml, encoding='utf8')}")

        payment_id: int = int(xml.findtext("source_payment", default=""))
        payment_info = payment.PaymentInfo(payment_id, language=None)
  
        is_test = self.__convert_is_test_to_bool(payment_info.paymethod['test'])  # type: ignore
        api_key: str = payment_info.paymethod['api_key']  # type: ignore
        secret_key: str = payment_info.paymethod['secret_key']  # type: ignore

        api = PayssionAPI(api_key=api_key, secret_key=secret_key, is_test=is_test)
        if not api.is_api_ok():
            logger.info(
                "API is down; unable to create paymethod now")
            raise billmgr.exception.XmlException("payssion_api_down")

        transaction_id = payment_info.payment["externalid"]
        order_id = payment_info.payment["number"]
        api.make_refund(transaction_id, order_id) # type: ignore

    def __set_bill_payment_status(self, _id: int, payment_detail: dict, payssion_api: PayssionAPI, created_at: str):
        """Set payment status in billmgr depending on the NOWPayment's payment

        Keyword arguments:
        _id -- this payment's elid (billmgr)
        payment_detail -- Payssion payment 
        payment_ api -- Payssion API
        created_at -- the day this payment has been created at
        """
        external_id = payment_detail["transaction_id"]
        status = payment_detail["state"]
        logger.info("set_status")
        logger.info(
                f"paid payment wtih id {_id} and external id {external_id}")
        if status == PaymentStatus.COMPLETED.value:
            payment.set_paid(_id, info="paid",
                             external_id=external_id)
            logger.info(
                f"paid payment wtih id {_id} and external id {external_id}")
        elif status == PaymentStatus.PAID_PARTIAL.value:
            payssion_api.make_refund(payment_detail["transaction_id"], payment_detail["order_id"])
            payment.set_canceled(_id, info="refund",
                             external_id=external_id)
            logger.info(
                f"refund partial payment wtih id {_id} and external id {external_id}")

        elif status == PaymentStatus.FAILED.value:
            payment.set_canceled(_id, info="failed",
                                 external_id=external_id)
            logger.info(
                f"cancelled payment wtih id {_id} and external id {external_id} because failed")

        elif status == PaymentStatus.EXPIRED.value:
            payment.set_canceled(_id, info="expired",
                                 external_id=external_id)
            logger.info(
                f"cancelled payment wtih id {_id} and external id {external_id} because expired")

        elif abs((datetime.strptime(created_at, "%Y-%m-%d %H:%M:%S") - datetime.today()).days) > 7:
            payment.set_canceled(_id, info="outdated",
                                 external_id=external_id)
            logger.info(
                f"cancelled payment wtih id {_id} and external id {external_id} because outdated")

        elif status in {PaymentStatus.PENDING.value,
                        PaymentStatus.AWAITING_CONFIRM.value}:
            logger.info(
                f"in pay payment wtih id {_id} and external id {external_id}")

        else:
            logger.error(
                f"No directions for payment with status \"{status}\", "
                f"invoice id = {external_id}, bill payment id = {_id}"
            )

    def __convert_is_test_to_bool(self, is_test: str = "on") -> bool:
        """Convert BILLmanager paymethod string "is_test" value to a boolean value

        Keyword arguments:
        is_test -- BILLmanager paymethod value equivalent to "is_test"
        """
        return is_test == "on"


if __name__ == "__main__":
    PayssionModule().run()
