from abc import ABC, abstractmethod

from oscar.core.loading import get_class, get_model

Voucher = get_model("voucher", "Voucher")
LineAttribute = get_model("basket", "LineAttribute")
Selector = get_class("partner.strategy", "Selector")


class FakeBasket:
    """Wrapper class for creating orders received by online marketplaces"""

    is_empty = False

    def __init__(self, fake_line_class, lines):
        self.lines = lines
        self.fake_line_class = fake_line_class

    @property
    def offer_applications(self):
        # offers are handled within the online marketplace
        return []

    @property
    def vouchers(self):
        # vouchers are handled within the online marketplace
        return Voucher.objects.none()

    def all_lines(self):
        for line in self.lines:
            yield self.fake_line_class(line)


class FakeLine(ABC):
    def __init__(self, item):
        self.item = item

    @property
    def attributes(self):
        # OrderCreator expects a queryset but we don't care
        return LineAttribute.objects.none()

    @property
    def stockrecord(self):
        return self.purchase_info.stockrecord

    @property
    def purchase_info(self):
        strategy = Selector().strategy()
        return strategy.fetch_for_product(self.product)

    def get_price_breakdown(self):
        # We do not care about the price breakdown since all payments are handeld by the online marketplace
        return {}

    @property
    def discounts(self):
        # We do not care about discounts, prices like we recieve them is what the customer paid
        return []

    @property
    @abstractmethod
    def product(self):
        pass

    @property
    @abstractmethod
    def quantity(self):
        pass

    @property
    @abstractmethod
    def line_price_excl_tax_incl_discounts(self):
        pass

    @property
    @abstractmethod
    def line_price_incl_tax_incl_discounts(self):
        pass

    @property
    @abstractmethod
    def line_price_excl_tax(self):
        pass

    @property
    @abstractmethod
    def line_price_incl_tax(self):
        pass

    @property
    @abstractmethod
    def unit_price_incl_tax(self):
        pass

    @property
    @abstractmethod
    def unit_price_excl_tax(self):
        pass

    @property
    def tax_code(self):
        return self.product.vat_rate
