from django.conf import settings
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"
)
get_vat_info_for_country = get_class("partner.utils", "get_vat_info_for_country")


class OrderCreator(BaseOrderCreator):
    # default value for shipping_country
    shipping_country = settings.OSCAR_VAT_COUNTRY_OF_ORIGIN_CODE

    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)

        # pylint: disable=W0201
        if shipping_address:
            self.shipping_country = shipping_address.country.pk
        else:
            self.shipping_country = settings.OSCAR_VAT_COUNTRY_OF_ORIGIN_CODE

        if shipping_charge.tax_code:
            shipping_tax_code = get_vat_info_for_country(
                shipping_charge.tax_code, self.shipping_country, True, user=user
            ).tax_code
        else:
            shipping_tax_code = None

        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_tax_code": shipping_tax_code,
            "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:
                tax_code = get_vat_info_for_country(
                    charge.price.tax_code, self.shipping_country, False, user=user
                ).tax_code
                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,
                    tax_code=tax_code,
                )

        return order

    def get_tax_code_from_basket_line(self, basket_line, order):
        return get_vat_info_for_country(
            basket_line.tax_code or basket_line.product.vat_rate,
            self.shipping_country,
            False,
            user=order.user,
        ).tax_code

    def create_line_price_models(self, order, order_line, basket_line):
        """
        Creates the batch line price models
        """
        breakdown = basket_line.get_price_breakdown()
        for price_incl_tax, price_excl_tax, quantity in breakdown:
            order_line.prices.create(
                order=order,
                quantity=quantity,
                price_incl_tax=price_incl_tax,
                price_excl_tax=price_excl_tax,
                tax_code=self.get_tax_code_from_basket_line(basket_line, order),
            )

    def create_additional_line_models(self, order, order_line, basket_line):
        order_line.tax_code = self.get_tax_code_from_basket_line(basket_line, order)
        order_line.save()
