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

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': 14,
            'MYR': 42
        },
        'subscription': {
            'SGD': 10,
            'MYR': 30
        }
    },
    'premium': {
        'oneoff': {
            'SGD': 18,
            'MYR': 42
        },
        'subscription': {
            'SGD': 14,
            'MYR': 42
        }
    }
}


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'

    def create_child(self, product, 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
        )

        # 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 handle(self, *args, **options):

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

            print('Starting migrations')
            # 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'
                },

            }

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

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

            total_coffees = coffee_types.count()
            finished = 0
            for coffee in coffee_types:
                print('Finished {} of {}'.format(finished, total_coffees))
                # Check if the product is already in the database then skip adding.
                #if Transient.objects.filter(content_type=product_content_type).filter(old_pk=coffee.id).exists():
                #    continue
                parent = Product(
                    structure=Product.PARENT,
                    title=coffee.name,
                    description=coffee.description_en,
                    product_class=coffee_product_type,
                    live=bool(coffee.mode)
                )

                parent.save()
                # 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) if x else 0, 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 transient
                Transient.objects.create(
                    content_type=product_content_type,
                    new_pk=parent.pk,
                    old_pk=coffee.id,
                    old_model=coffee.__class__.__name__
                )

                # Create the subscription products.
                self.create_child(parent, False)
                self.create_child(parent, True)

                finished += 1
                print('Finished {}/{}'.format(crayons.red(finished), crayons.blue(total_coffees)))
