# Path: billing/psp.py
# class PSP:
#     """ Each PSP must implement these methods. """
# 
#     def model_classes(self) -> List[Model]:
#         """
#         :return: the list of model classes that this psp is responsible for.
#         """
#         pass
# 
#     def charge_credit_card(self, credit_card_psp_object: Model, amount: Money, client_ref: str) -> Tuple[bool, Model]:
#         """
#         :param credit_card_psp_object: an instance representing the credit card in the psp
#         :param amount: the amount to charge
#         :param client_ref: a reference that will appear on the customer's credit card report
#         :return: a tuple (success, payment_psp_object)
#         """
#         pass
# 
#     def refund_payment(self, payment_psp_object: Model, amount: Money, client_ref: str) -> Tuple[bool, Model]:
#         """
#         :param payment_psp_object: an instance representing the original payment in the psp
#         :param amount: the amount to refund
#         :param client_ref: a reference that will appear on the customer's credit card statement
#         :return: a tuple (success, refund_psp_object)
#         """
#         pass
# 
#     class Meta:
#         abstract = True
# 
# Path: tests/models.py
# class MyPSPCreditCard(models.Model):
#     id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
#     token = models.CharField(max_length=20)
# 
# class MyPSPPayment(models.Model):
#     id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
#     payment_ref = models.CharField(max_length=20)
# 
# class MyPSPRefund(models.Model):
#     id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
#     refund_ref = models.CharField(max_length=20)


from django.db.models import Model
from moneyed import Money
from typing import Tuple
from billing.psp import PSP
from .models import MyPSPCreditCard, MyPSPPayment, MyPSPRefund



class MyPSP(PSP):
    """
    Always succeeds, and remembers how it was invoked (like a mock)
    """

    def __init__(self):
        self.charges = []
        self.refunds = []

    def model_classes(self):
        return [MyPSPPayment, MyPSPCreditCard]

    def charge_credit_card(self, credit_card_psp_object: Model, amount: Money, client_ref: str) -> Tuple[bool, Model]:
        self.charges.append(dict(amount=amount, client_ref=client_ref))

# Path: billing/psp.py
# class PSP:
#     """ Each PSP must implement these methods. """
# 
#     def model_classes(self) -> List[Model]:
#         """
#         :return: the list of model classes that this psp is responsible for.
#         """
#         pass
# 
#     def charge_credit_card(self, credit_card_psp_object: Model, amount: Money, client_ref: str) -> Tuple[bool, Model]:
#         """
#         :param credit_card_psp_object: an instance representing the credit card in the psp
#         :param amount: the amount to charge
#         :param client_ref: a reference that will appear on the customer's credit card report
#         :return: a tuple (success, payment_psp_object)
#         """
#         pass
# 
#     def refund_payment(self, payment_psp_object: Model, amount: Money, client_ref: str) -> Tuple[bool, Model]:
#         """
#         :param payment_psp_object: an instance representing the original payment in the psp
#         :param amount: the amount to refund
#         :param client_ref: a reference that will appear on the customer's credit card statement
#         :return: a tuple (success, refund_psp_object)
#         """
#         pass
# 
#     class Meta:
#         abstract = True
# 
# Path: tests/models.py
# class MyPSPCreditCard(models.Model):
#     id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
#     token = models.CharField(max_length=20)
# 
# class MyPSPPayment(models.Model):
#     id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
#     payment_ref = models.CharField(max_length=20)
# 
# class MyPSPRefund(models.Model):
#     id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
#     refund_ref = models.CharField(max_length=20)


# Path: tests/my_psp.py
from django.db.models import Model
from moneyed import Money
from typing import Tuple
from billing.psp import PSP
from .models import MyPSPCreditCard, MyPSPPayment, MyPSPRefund




class MyPSP(PSP):
    """
    Always succeeds, and remembers how it was invoked (like a mock)
    """

    def __init__(self):
        self.charges = []
        self.refunds = []

    def model_classes(self):
        return [MyPSPPayment, MyPSPCreditCard]

    def charge_credit_card(self, credit_card_psp_object: Model, amount: Money, client_ref: str) -> Tuple[bool, Model]:
        self.charges.append(dict(amount=amount, client_ref=client_ref))

        payment = MyPSPPayment.objects.create(payment_ref='payment_12345')