from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.db import models


class MyAccountManager(BaseUserManager):
    def create_user(self, email, username, password=None):
        if not email:
            raise ValueError('Users must have an email address')
        if not username:
            raise ValueError('Users must have a username')

        user = self.model(
            email=self.normalize_email(email),
            username=username,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, username, password):
        user = self.create_user(
            email=self.normalize_email(email),
            password=password,
            username=username,
        )
        user.is_admin = True
        user.is_staff = True
        user.is_superuser = True
        user.save(using=self._db)
        return user


class Account(AbstractBaseUser):
    email = models.EmailField(verbose_name="email", max_length=60, unique=True)
    username = models.CharField(max_length=30, unique=True)
    date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
    last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
    is_admin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    hide_email = models.BooleanField(default=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    objects = MyAccountManager()

    def __str__(self):
        return self.username

    def has_perm(self, perm, obj=None):
        return self.is_admin

    def has_module_perms(self, app_label):
        return True


class Department(models.Model):
    dep_name = models.CharField(max_length=255)
    item_image = models.ImageField(null=True, blank=True)

    def __str__(self):
        return self.dep_name

    @property
    def imageURL(self):
        try:
            url = self.item_image.url
        except:
            url = ''
        return url


class Item(models.Model):
    item_name = models.CharField(max_length=255)
    item_desc = models.TextField('item_desc')
    item_cost = models.IntegerField()
    item_quantity = models.IntegerField(default=0)
    item_rate = models.FloatField(default=0.0)
    num_of_views = models.IntegerField(default=0)
    item_image = models.ImageField(null=True, blank=True)
    digital = models.BooleanField(default=False, null=True, blank=False)
    dep_id = models.ForeignKey(Department, on_delete=models.CASCADE)

    def __str__(self):
        return f"{self.item_name} ({self.dep_id})"

    @property
    def imageURL(self):
        try:
            url = self.item_image.url
        except:
            url = ''
        return url

    def get_numberOfViews(self):
        return self.num_of_views


class Order(models.Model):
    customer = models.ForeignKey(Account, on_delete=models.SET_NULL, null=True, blank=True)
    date_ordered = models.DateTimeField(auto_now_add=True)
    complete = models.BooleanField(default=False)
    transaction_id = models.CharField(max_length=100, null=True)

    def __str__(self):
        return str(self.id)

    @property
    def shipping(self):
        shipping = False
        orderitems = self.orderitem_set.all()
        for i in orderitems:
            if not i.product.digital:
                shipping = True
        return shipping

    @property
    def get_cart_total(self):
        orderitems = self.orderitem_set.all()
        total = sum([item.get_total for item in orderitems])
        return total

    @property
    def get_cart_items(self):
        orderitems = self.orderitem_set.all()
        total = sum([item.quantity for item in orderitems])
        return total


class OrderItem(models.Model):
    product = models.ForeignKey(Item, on_delete=models.SET_NULL, null=True)
    order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
    quantity = models.IntegerField(default=0, null=True, blank=True)
    date_added = models.DateTimeField(auto_now_add=True)

    @property
    def get_total(self):
        total = self.product.item_cost * self.quantity
        return total


class ShippingAddress(models.Model):
    customer = models.ForeignKey(Account, on_delete=models.SET_NULL, null=True)
    order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
    address = models.CharField(max_length=200, null=False)
    city = models.CharField(max_length=200, null=False)
    state = models.CharField(max_length=200, null=False)
    zipcode = models.CharField(max_length=200, null=False)
    date_added = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.address


class Wishlist(models.Model):
    customer = models.ForeignKey(Account, on_delete=models.SET_NULL, null=True, blank=True)

class WishlistItem(models.Model):
    product = models.ForeignKey(Item, on_delete=models.SET_NULL, null=True)
    wishlist = models.ForeignKey(Wishlist, on_delete=models.SET_NULL, null=True)


class FindLocation(models.Model):
    location = models.CharField(max_length=200)
    deliveryAddress = models.CharField(max_length=200)
    distance = models.DecimalField(max_digits=10, decimal_places=2)
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Our nearest shop {self.location} is {self.distance}km away from you {self.deliveryAddress}."

