from django.views.generic import View
from django.contrib import messages
from oscar.core.loading import get_model
from django.conf import settings
from django.http.response import JsonResponse, HttpResponseRedirect
import itertools
import uuid
from django.shortcuts import reverse


Product = get_model('catalogue', 'Product')
ProductAttribute = get_model('catalogue', 'ProductAttribute')
ProductAttributeValue = get_model('catalogue', 'ProductAttributeValue')
ProductClass = get_model('catalogue', 'ProductClass')
StockRecord = get_model('partner', 'StockRecord')
Partner = get_model('partner', 'Partner')


class CreateVariantsView(View):
    """
    Create all variants for the given product.
    Create the stock records for all difference currencies.
    """

    def make_baby(self, product, combination, subscription=False):
        # Create the sub products
        child = Product.objects.create(
            structure=product.CHILD,
            parent=product,
            slug=product.slug,
            is_discountable=1,
            subscription=subscription
        )

        # Add the attributes
        for option in combination:
            ProductAttributeValue.objects.create(
                attribute=option.group.product_attributes.filter(product_class=product.product_class).first(),
                product=child,
                value_option=option,
            )

        # Add the stock records.
        partner = Partner.objects.order_by('pk').first()
        currencies = set([c['currency'] for c in getattr(settings, 'SUPPORTED_COUNTRIES')])

        for currency in currencies:
            sku = uuid.uuid4()
            StockRecord.objects.create(
                product=child,
                partner=partner,
                price_currency=currency,
                partner_sku=sku.hex,
            )

    def get(self, *args, **kwargs):
        product = Product.objects.get(pk=self.kwargs.get('pk'))
        attributes = ProductAttribute.objects.filter(product_class=product.product_class).filter(
            use_for_variations=True, option_group__isnull=False).prefetch_related('option_group',
                                                                                  'option_group__options').distinct().all()

        # Get all attribute combinations
        attr_list = []
        children_born = 0
        for attribute in attributes:
            attr_list.append(attribute.option_group.options.all())

        combinations = list(itertools.product(*attr_list))

        try:
            for combination in combinations:
                self.make_baby(product, combination)

        except Exception as e:
            messages.error(self.request, str(e))
            return HttpResponseRedirect(reverse('dashboard:catalogue-product', kwargs={'pk': product.pk}))
        messages.success(self.request, "{} babies were made !".format(children_born))
        return HttpResponseRedirect(reverse('dashboard:catalogue-product', kwargs={'pk': product.pk}))


class CreateSubscriptionVariant(View):
    """
    Create a clone of the given product or child.
    """

    def get(self, *args, **kwargs):
        product_id = self.kwargs.get('pk')
        product = Product.objects.get(pk=product_id)
        product.pk = None
        product.subscription = True
        product.save()

        for attr in ProductAttributeValue.objects.filter(product_id=product_id).all():
            attr.pk = None
            attr.product = product
            attr.save()

        for record in StockRecord.objects.filter(product_id=product_id).all():
            record.product = product
            record.pk = None
            record.partner_sku = uuid.uuid4().hex
            record.save()
        messages.success(self.request, 'Success')
        return HttpResponseRedirect(reverse('dashboard:catalogue-product', kwargs={'pk': product.parent_id}))
