from django.contrib.sites.models import Site

from oscar.core.loading import get_class, get_model

from ocyan.main.loading import get_baseclass

Order = get_model("order", "Order")
DeliveryTime = get_class("checkout.delivery", "DeliveryTime")
Surcharge = get_model("order", "Surcharge")
BaseOrderCreator = get_baseclass(
    "order.utils", "OrderCreator", "ocyan.plugin.oscar_order.order"
)


class OrderCreator(BaseOrderCreator):
    def create_order_model(
        self,
        user,
        basket,
        shipping_address,
        shipping_method,
        shipping_charge,
        billing_address,
        total,
        order_number,
        status,
        request=None,
        surcharges=None,
        **extra_order_fields,
    ):
        """Create an order model."""
        delivery_time = DeliveryTime.delivery_time(basket, request)

        order_data = {
            "basket": basket,
            "number": order_number,
            "currency": total.currency,
            "total_incl_tax": total.incl_tax,
            "total_excl_tax": total.excl_tax,
            "shipping_incl_tax": shipping_charge.incl_tax,
            "shipping_excl_tax": shipping_charge.excl_tax,
            "shipping_method": shipping_method.name,
            "shipping_code": shipping_method.code,
            "delivery_time_text": delivery_time.delivery_time_text,
            "delivery_time_days": delivery_time.delivery_time_days,
        }

        if shipping_address:
            order_data["shipping_address"] = shipping_address
        if billing_address:
            order_data["billing_address"] = billing_address
        if user and user.is_authenticated:
            order_data["user_id"] = user.id
        if status:
            order_data["status"] = status
        if extra_order_fields:
            order_data.update(extra_order_fields)
        if "site" not in order_data:
            # pylint: disable=protected-access
            order_data["site"] = Site._default_manager.get_current(request)

        order = Order(**order_data)
        order.save()
        if surcharges is not None:
            for charge in surcharges:
                Surcharge.objects.create(
                    order=order,
                    name=charge.surcharge.name,
                    code=charge.surcharge.code,
                    excl_tax=charge.price.excl_tax,
                    incl_tax=charge.price.incl_tax,
                )
        return order


class MarketplaceOrderCreator(OrderCreator):
    def create_order_model(
        self,
        user,
        basket,
        shipping_address,
        shipping_method,
        shipping_charge,
        billing_address,
        total,
        order_number,
        status,
        request=None,
        surcharges=None,
        **extra_order_fields,
    ):
        # Marketplace orders don't have a real basket instance, setting it to None will prevent it trying to create
        # a database relation between the order and basket.
        basket = None
        return super().create_order_model(
            user,
            basket,
            shipping_address,
            shipping_method,
            shipping_charge,
            billing_address,
            total,
            order_number,
            status,
            request,
            surcharges,
            **extra_order_fields,
        )
