from hookmigration.peewee_models import CustomauthMyuser, CustomersCustomer, CustomersGearorder, CoffeesCoffeegear, \
    CustomersAddress
from hookmigration.models import Transient
from oscar.core.loading import get_model
from apps.order.utils import OrderNumberGenerator
from django.core.management.base import BaseCommand
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from peewee import JOIN
from django.db import transaction
import crayons
import simplejson as json
from progressbar import ProgressBar
from django.utils import timezone

Order = get_model('order', 'Order')
Line = get_model('order', 'Line')
LinePrice = get_model('order', 'LinePrice')
UserAddress = get_model('address', 'UserAddress')
ShippingAddress = get_model('order', 'ShippingAddress')
Partner = get_model('partner', 'Partner')

user_content_type = ContentType.objects.get_for_model(User)
order_content_type = ContentType.objects.get_for_model(Order)
address_content_type = ContentType.objects.get_for_model(UserAddress)

STATUSES = {
    'AC': 'Being processed',
    'SH': 'Shipped',
    'PA': 'Pending',
    'CA': 'Cancelled',
    'ER': 'Error',
    'DE': 'Error'
}

partner = Partner.objects.first()


class Command(BaseCommand):
    """
    Please note.
    This migration unlike the previous ones, does not care about keeping the foreign key relationships to the product and stock records.
    """
    help = "Migrate all the gear orders from the old db to the new db"

    def hstore_to_json(self, text):
        text = text.strip()
        text = text.replace('NULL', '""')
        text = text.strip().replace('=>', ':')
        content = '{' + text + '}'
        try:
            return json.loads(content, strict=False)
        except Exception as e:
            print('--------------------------------------------------------------------------')
            print(text)
            print(e)
            print('--------------------------------------------------------------------------')
            exit()

    def handle(self, *args, **options):
        # All the shipped orders from gear orders.
        with transaction.atomic():
            orders = CustomersGearorder.select().join(
                CustomersCustomer, JOIN.LEFT_OUTER).switch(
                CustomersGearorder).join(CoffeesCoffeegear, JOIN.LEFT_OUTER).switch(
                CustomersGearorder).join(
                CustomersAddress, JOIN.LEFT_OUTER).distinct()
            total = orders.count()
            done = 0
            problem_users = []
            progress = ProgressBar(max_value=total)
            for order in orders:
                done += 1
                new_user_pk = Transient.objects.filter(old_pk=order.customer.user_id,
                                                       content_type=user_content_type).first()
                if not new_user_pk:
                    problem_users.append(order)
                    continue
                user = User.objects.get(pk=new_user_pk.new_pk)

                # check if the order has address then fetch the address, or default shipping address.
                if order.address:
                    new_address_id = Transient.objects.filter(old_pk=order.address_id,
                                                              content_type=address_content_type).first()
                    if new_address_id:
                        address = UserAddress.objects.get(pk=new_address_id.new_pk)
                    else:
                        address = UserAddress.objects.filter(user=user).first()
                else:
                    address = UserAddress.objects.filter(user=user).first()
                shipping_address = ShippingAddress()
                address.populate_alternative_model(shipping_address)
                shipping_address.save()

                order_data = self.hstore_to_json(order.details)
                quantity = int(order_data.get('quantity', 1))
                # create the order
                new_order = Order(
                    user=user,
                    number='G-{}'.format(order.id),
                    total_incl_tax=order.price,
                    total_excl_tax=order.price,
                    shipping_incl_tax=0,
                    shipping_excl_tax=0,
                    shipping_address=shipping_address,
                    shipping_method='singpost',
                    shipping_code='singpost',
                    status=STATUSES[order.status],
                    date_placed=timezone.localtime(order.date)
                )
                new_order.save()

                Transient.objects.create(
                    content_type=order_content_type,
                    old_pk=order.id,
                    new_pk=new_order.pk,
                    old_model=order.__class__.__name__
                )

                line = Line(
                    order=new_order,
                    partner=partner,
                    partner_name=partner.name,
                    partner_sku=order.gear_id,
                    title=order.gear.name,
                    quantity=quantity,
                    line_price_incl_tax=order.price,
                    line_price_excl_tax=order.price,
                    line_price_before_discounts_incl_tax=order.price,
                    line_price_before_discounts_excl_tax=order.price,
                    status=STATUSES[order.status],
                    est_dispatch_date=timezone.localtime(order.shipping_date).date()
                )
                line.save()

                line_price = LinePrice(
                    order=new_order,
                    line=line,
                    quantity=quantity,
                    price_incl_tax=order.price / quantity,
                    price_excl_tax=order.price / quantity,
                    shipping_incl_tax=0,
                    shipping_excl_tax=0,
                )
                line_price.save()
                progress.update(done)
