import pycountry

from hookmigration.peewee_models import CoffeesCoffeetype, CoffeesCoffeegear, CoffeesBrewmethod, \
    CoffeesCoffeegearBrewMethods, CoffeesCoffeetypeBrewMethod
from oscar.core.loading import get_model
from django.core.management import BaseCommand
import requests
from hookmigration.models import Transient
from django.conf import settings
import uuid
import itertools
from peewee import *
from django.db import transaction
from django.conf import settings
import os
from django.contrib.contenttypes.models import ContentType
from decimal import Decimal as D
import re
import crayons
from progressbar import ProgressBar

Product = get_model('catalogue', 'Product')
Category = get_model('catalogue', 'Category')
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')
ProductImage = get_model('catalogue', 'ProductImage')
ProductCategory = get_model('catalogue', 'ProductCategory')
AttributeOption = get_model('catalogue', 'AttributeOption')
AttributeOptionGroup = get_model('catalogue', 'AttributeOptionGroup')
Country = get_model('address', 'Country')

image_base_location = 'https://hookcoffee.com.sg/media/{}'
image_save_location = os.path.join(getattr(settings, 'MEDIA_ROOT'), 'images', 'products', 'migrated')

product_content_type = ContentType.objects.get_for_model(Product)

prices = {
    'classic': {
        'oneoff': {
            'SGD': 18,
            'MYR': 54
        },
        'subscription': {
            'SGD': 14,
            'MYR': 42
        }
    },
    'premium': {
        'oneoff': {
            'SGD': 22,
            'MYR': 66
        },
        'subscription': {
            'SGD': 18,
            'MYR': 54
        }
    }
}


class Command(BaseCommand):
    """
    1. Get the Coffee Types first
    2. Create the Coffee, Child Products. Stockrecords for the product
    3. Save the Transient
    """
    help = 'MIgrate all the products'

    option_whole_beans = AttributeOption.objects.get(option='Whole Beans')
    option_ground = AttributeOption.objects.get(option='Ground')
    option_drip_bags = AttributeOption.objects.get(option='Drip Bags')
    option_80g = AttributeOption.objects.get(option='80g')
    option_200g = AttributeOption.objects.get(option='200g')
    option_1kg = AttributeOption.objects.get(option='1kg')
    option_10_drip_bags = AttributeOption.objects.get(option='10 Drip Coffee Bags')

    def create_child(self, product, combination, subscription=False):
        if product.attribute_dict['premium']['value']:
            coffee_type = 'premium'
        else:
            coffee_type = 'classic'

        if subscription:
            purchase_type = 'subscription'
        else:
            purchase_type = 'oneoff'

        # Create the sub products
        child = Product.objects.create(
            structure=product.CHILD,
            parent=product,
            slug=product.slug,
            is_discountable=1,
            subscription=subscription,
            live=bool(product.live)
        )

        # 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,
                price_excl_tax=D(prices[coffee_type][purchase_type][currency])
            )

    def get_combinations(self):
        return [(self.option_ground, self.option_80g),
                (self.option_ground, self.option_200g),
                (self.option_ground, self.option_1kg),
                (self.option_whole_beans, self.option_80g),
                (self.option_whole_beans, self.option_200g),
                (self.option_whole_beans, self.option_1kg),
                (self.option_drip_bags, self.option_10_drip_bags)]

    def get_subscription_combinations(self):
        return [(self.option_ground, self.option_200g),
                (self.option_whole_beans, self.option_200g),
                (self.option_drip_bags, self.option_10_drip_bags)]

    def handle(self, *args, **options):

        with transaction.atomic():
            coffee_product_type = ProductClass.objects.filter(slug='coffee-bag').first()
            coffee_category = Category.objects.filter(slug='by-the-bag').first()

            # Product image directory

            mapping = {
                'acidity': {
                    'field_name': 'acidity',
                    'type': 'option',
                },
                'altitude': {
                    'field_name': 'altitude',
                    'type': 'text'
                },
                'country': {
                    'field_name': 'country',
                    'type': 'query'  # from the country databases
                },
                'intensity': {
                    'field_name': 'intensity',
                    'type': 'int'
                },
                'maker': {
                    'field_name': 'coffee_producer',
                    'type': 'text'
                },
                'more_taste': {
                    'field_name': 'more_taste',
                    'type': 'text'
                },
                'process': {
                    'field_name': 'process',
                    'type': 'text'
                },
                'profile': {
                    'field_name': '',
                    'type': 'map',
                    'map': {
                        1: 'berries',
                        2: 'caramel',
                        3: 'chocolate',
                        4: 'citrus_lemons',
                        5: 'edible_flowers',
                        6: 'stone_fruits',
                        7: 'none'
                    }
                },

                'region': {
                    'field_name': 'region',
                    'type': 'text'
                },

                'special': {
                    'field_name': 'premium',
                    'type': 'boolean'
                },

                'taste': {
                    'field_name': 'coffee_taste',
                    'type': 'text'
                },

                'varietal': {
                    'field_name': 'varietal',
                    'type': 'text'
                },

            }

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

            # Find the products
            coffee_types = CoffeesCoffeetype.select().join(CoffeesCoffeetypeBrewMethod).where(
                ~(CoffeesCoffeetype.name ** '%pods%') & (CoffeesCoffeetypeBrewMethod.brewmethod != 6)
            ).distinct()

            attribute_base_query = ProductAttribute.objects.filter(product_class=coffee_product_type)

            total_coffees = coffee_types.count()
            finished = 0
            progress = ProgressBar(max_value=total_coffees)
            for coffee in coffee_types:
                parent = Product(
                    structure=Product.PARENT,
                    title=coffee.name,
                    description=coffee.description_en,
                    product_class=coffee_product_type,
                    live=bool(coffee.mode)
                )

                parent.save()
                # Create the transient
                Transient.objects.create(
                    content_type=product_content_type,
                    new_pk=parent.pk,
                    old_pk=coffee.id,
                    old_model=coffee.__class__.__name__
                )
                # Add the category
                ProductCategory.objects.create(product=parent, category=coffee_category, primary=True)

                # Down load the image and add the image
                # file_name = coffee.img.replace('./', '')
                # image_url = image_base_location.format(file_name)
                # content = requests.get(image_url).content
                # with open(os.path.join(image_save_location, file_name), 'wb') as file:
                #    file.write(content)

                # original = os.path.relpath(os.path.join(image_save_location, file_name),getattr(settings, 'MEDIA_ROOT'))

                # ProductImage.objects.create(product=parent, original=original)

                # Add the attributes
                for key, value in mapping.items():
                    if value['type'] in ['int', 'text', 'boolean']:
                        attribute = attribute_base_query.filter(code=value['field_name']).first()
                        if value['type'] == 'int':
                            ProductAttributeValue.objects.create(
                                value_integer=getattr(coffee, key),
                                attribute=attribute,
                                product=parent
                            )
                        if value['type'] == 'text':
                            ProductAttributeValue.objects.create(
                                value_text=getattr(coffee, key),
                                attribute=attribute,
                                product=parent
                            )
                        if value['type'] == 'boolean':
                            ProductAttributeValue.objects.create(
                                value_boolean=getattr(coffee, key),
                                attribute=attribute,
                                product=parent
                            )

                    if key == 'acidity':
                        if coffee.acidity == 1:
                            acidity = AttributeOption.objects.get(pk=12)
                        elif coffee.acidity == 2:
                            acidity = AttributeOption.objects.get(pk=13)
                        elif coffee.acidity == 3:
                            acidity = AttributeOption.objects.get(pk=14)
                        else:
                            acidity = AttributeOption.objects.get(pk=12)

                        ProductAttributeValue.objects.create(
                            value_option=acidity,
                            attribute=attribute_base_query.filter(code='acidity').first(),
                            product=parent
                        )
                    if key == 'country':
                        country = pycountry.countries.get(alpha_2=coffee.country)
                        ProductAttributeValue.objects.create(
                            value_text=country.name,
                            attribute=attribute_base_query.filter(code='country').first(),
                            product=parent
                        )
                    if key == 'profile':

                        pattern = r'"([A-Za-z0-9_\./\\-]*)"'
                        result = re.findall(pattern, coffee.profile)
                        result = list(map(lambda x: int(x), result))
                        if len(result) < 4:
                            continue
                        profile = dict(zip(result[0::2], result[1::2]))
                        for id, value in profile.items():
                            attribute = attribute_base_query.filter(code=mapping['profile']['map'][id]).first()
                            ProductAttributeValue.objects.create(
                                value_integer=value,
                                attribute=attribute,
                                product=parent
                            )
                # Create the child products

                # Create the one off products.
                for combination in self.get_combinations():
                    self.create_child(parent, combination, False)

                # Create the subscription products.
                for combination in self.get_subscription_combinations():
                    self.create_child(parent, combination, True)

                finished += 1
                progress.update(finished)
