import logging
import stripe
from io import BytesIO

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.db import models
from django.conf import settings

from . import OrderStatus, TransactionStatus
from .models import Product, Order, OrderLine, Transaction, TrackingNumber
from .tasks import (
    send_order_confirmation_email,
    send_order_shipped_email
)

logger = logging.getLogger(__name__)


@receiver(post_save, sender=Product, dispatch_uid="product_created")
def product_saved(sender, instance, created, **kwargs):
    logger.info('Product was saved')
    if created or not instance.stripe_id:
        stripe.api_key = settings.STRIPE_API_KEY
        response = stripe.Product.create(
            name=instance.name,
            description=instance.description
        )
        instance.stripe_id = response['id']
        instance.save()


@receiver(post_save, sender=Order, dispatch_uid="order_created")
def order_created(sender, instance, created, **kwargs):
    if created:
        logger.info("Order was created")
        Transaction.objects.create(order=instance)


@receiver(post_save, sender=Transaction, dispatch_uid="transaction_created")
def transaction_created(sender, instance, created, **kwargs):
    if created:
        logger.info("Transaction was created")

    elif instance.status == TransactionStatus.COMPLETED and not instance.confirmation_email_sent:
        # TODO: change order to order.values()
        order = {
            'order_id': instance.order.pk,
            'email': instance.order.customer.email,
            'full_name': instance.order.customer.get_full_name()
        }
        send_order_confirmation_email.delay(order)
        instance.confirmation_email_sent = True
        instance.save()


@receiver(post_save, sender=TrackingNumber, dispatch_uid="trackingnumber_postsave")
def trackingnumber_postsave(sender, instance, created, **kwargs):
    if created:
        logger.info("TrackingNumber was created")

        data = {
            'order_id': instance.order.pk,
            'email': instance.order.customer.email,
            'full_name': instance.order.customer.get_full_name(),
            'tracking_id': instance.tracking_id
        }
        send_order_shipped_email.delay(data)


def get_order_status(total_quantity_fulfilled, total_quantity_ordered):
    if total_quantity_fulfilled >= total_quantity_ordered:
        return OrderStatus.FULFILLED
    elif total_quantity_fulfilled > 0:
        return OrderStatus.PARTIALLY_FULFILLED
    else:
        return OrderStatus.UNFULFILLED


@receiver(post_save, sender=OrderLine, dispatch_uid="order_line_post_save")
def order_line_post_save(sender, instance, created, **kwargs):
    if not created:
        order = Order.objects.with_fulfillment().filter(
            pk=instance.order.pk
        )[0]

        order.status = get_order_status(order.total_quantity_fulfilled, order.total_quantity_ordered)
        order.save()

        # order.update(
        #     status=models.Case(
        #         models.When(models.lookups.GreaterThan(models.F('total_quantity_fulfilled'), models.F('total_quantity_ordered')),
        #             then=models.Value(OrderStatus.FULFILLED)),
        #         models.When(models.lookups.GreaterThan(models.F('total_quantity_fulfilled'), 0),
        #             then=models.Value(OrderStatus.PARTIALLY_FULFILLED)),
        #         default=models.Value(OrderStatus.UNFULFILLED)
        #     )
        # )
