from django.db import models
from django.conf import settings
from django.utils import timezone

class OrderStatus(models.TextChoices):
    PENDING = 'PENDING', 'Pending'
    PAID = 'PAID', 'Paid'
    SHIPPED = 'SHIPPED', 'Shipped'
    DELIVERED = 'DELIVERED', 'Delivered'
    CANCELED = 'CANCELED', 'Canceled'
    REFUNDED = 'REFUNDED', 'Refunded'
    PREPARED = 'PREPARED', 'Prepared'
    READY = 'READY', 'Ready'

class CutChoices(models.IntegerChoices):
    UNISEX = 0, 'Unisex'
    WOMEN = 1, 'Women'
    MEN = 2, 'Men'
    KIDS = 3, 'Kids'

class Color(models.Model):
    name = models.CharField(max_length=40, unique=True)
    colorHex = models.CharField(max_length=7, default="#FFFFFF", help_text="Color in hex format (e.g. #FF0000)")
    secondary_hex_color = models.CharField(max_length=7, null=True, blank=True,
                                          help_text="Secondary color in hex format for split color display")
    ordering = models.IntegerField(default=0)

    class Meta:
        ordering = ['ordering']  # This will make queries respect the ordering by default

    def __str__(self):
        return self.name

class Size(models.Model):
    name = models.CharField(max_length=20, unique=True)

    def __str__(self):
        return self.name

class Product(models.Model):
    sku = models.CharField(max_length=50, unique=True, help_text="Product SKU (unique identifier)")
    title = models.CharField(max_length=200)
    description = models.TextField(blank=True, null=True, help_text="Product description text")
    image = models.CharField(max_length=200, null=True, blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    # Use string references to prevent circular imports
    colors = models.ManyToManyField("shop.Color", blank=True, related_name="products")
    sizes = models.ManyToManyField("shop.Size", blank=True, related_name="products")
    ordering_value = models.IntegerField(default=0, blank=False)
    cut = models.IntegerField(choices=CutChoices.choices, default=CutChoices.UNISEX)

    class Meta:
        ordering = ['ordering_value', 'cut']  # Add this line to sort by title

    def __str__(self):
        return f"{self.sku} - {self.title}"

class CartItem(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField(default=1)
    color = models.ForeignKey(Color, on_delete=models.SET_NULL, null=True, blank=True)
    size = models.ForeignKey(Size, on_delete=models.SET_NULL, null=True, blank=True)
    session_id = models.CharField(max_length=255, null=True, blank=True)
    date_added = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['product__ordering_value', 'product__cut']  # Sort by product's ordering_value

    def __str__(self):
        return f"{self.quantity} x {self.product.title}"

    def get_total_price(self):
        return self.product.price * self.quantity

class ShippingAddress(models.Model):
    street_address = models.CharField(max_length=255)
    apartment = models.CharField(max_length=50, blank=True, null=True)
    city = models.CharField(max_length=100)
    state = models.CharField(max_length=100, blank=True, null=True)
    postal_code = models.CharField(max_length=20)
    country = models.CharField(max_length=100)

class GuestUser(models.Model):
    email = models.EmailField()
    phone = models.CharField(max_length=20)

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

class Coupon(models.Model):
    code = models.CharField(max_length=50, unique=True)
    description = models.CharField(max_length=255, blank=True)
    discount_amount = models.DecimalField(max_digits=10, decimal_places=2, default=0)
    discount_percent = models.DecimalField(max_digits=5, decimal_places=2, default=0)
    is_active = models.BooleanField(default=True)
    valid_from = models.DateTimeField()
    valid_to = models.DateTimeField()
    max_uses = models.IntegerField(default=0)  # 0 for unlimited
    current_uses = models.IntegerField(default=0)
    created_at = models.DateTimeField(auto_now_add=True)
    stripe_coupon_id = models.CharField(max_length=100, blank=True, null=True)

    def __str__(self):
        return self.code

    def is_valid(self):
        now = timezone.now()
        if not self.is_active:
            return False
        if now < self.valid_from or now > self.valid_to:
            return False
        if self.max_uses > 0 and self.current_uses >= self.max_uses:
            return False
        return True

    def get_discount_amount_for_total(self, total_price):
        """Calculate the discount amount for a given total price"""
        if self.discount_percent > 0:
            return (self.discount_percent / 100) * total_price
        return self.discount_amount

class Order(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True)
    shipping_address = models.ForeignKey(ShippingAddress, on_delete=models.SET_NULL, null=True, blank=True)
    date_ordered = models.DateTimeField(auto_now_add=True)
    status = models.CharField(max_length=20, choices=OrderStatus.choices, default=OrderStatus.PENDING)
    total_price = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    guest_user = models.ForeignKey(GuestUser, on_delete=models.CASCADE, null=True, blank=True)
    stripe_payment_intent_id = models.CharField(max_length=255, blank=True, null=True)
    stripe_checkout_session_id = models.CharField(max_length=255, blank=True, null=True)
    payment_status = models.CharField(max_length=20, default='UNPAID', choices=[
        ('UNPAID', 'Unpaid'),
        ('PAID', 'Paid'),
        ('FAILED', 'Failed'),
        ('REFUNDED', 'Refunded')
    ])
    webhook_processed = models.BooleanField(default=False)
    stripe_mode = models.CharField(max_length=10, default='test', choices=[
        ('test', 'Test Mode'),
        ('live', 'Live Mode'),
    ])
    coupon = models.ForeignKey(Coupon, on_delete=models.SET_NULL, null=True, blank=True)
    discount_amount = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    def __str__(self):
        return f"Order #{self.id} - {self.status}"

    def get_total_after_discount(self):
        return max(self.total_price - self.discount_amount, 0)

    def is_cancellable(self):
        """Check if the order can be cancelled"""
        return self.status in [OrderStatus.PENDING, OrderStatus.PAID]

    def shipping_address_can_be_edited(self):
        return self.status in [OrderStatus.PENDING, OrderStatus.PAID, OrderStatus.PREPARED, OrderStatus.READY]

    def get_shipping_address(self):
        """
        Returns a formatted string of the shipping address
        """
        if not self.shipping_address:
            return "Aucune adresse de livraison fournie"

        address_parts = [
            self.shipping_address.street_address,
            self.shipping_address.apartment if self.shipping_address.apartment else None,
            self.shipping_address.city,
            self.shipping_address.state if self.shipping_address.state else None,
            self.shipping_address.postal_code,
            self.shipping_address.country
        ]

        # Filter out None values and join with newlines
        formatted_address = '\n'.join(part for part in address_parts if part)
        return formatted_address

class OrderItem(models.Model):
    order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='items')
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField(default=1)
    color = models.ForeignKey(Color, on_delete=models.SET_NULL, null=True, blank=True)
    size = models.ForeignKey(Size, on_delete=models.SET_NULL, null=True, blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)

    class Meta:
        ordering = ['product__ordering_value', 'product__cut']  # Sort by product's ordering_value

    def __str__(self):
        return f"{self.quantity} x {self.product.title}"

    def get_total_price(self):
        return self.price * self.quantity

class CouponUsage(models.Model):
    coupon = models.ForeignKey(Coupon, on_delete=models.CASCADE, related_name='usages')
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True)
    order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='coupon_usages')
    guest_email = models.EmailField(blank=True, null=True)
    used_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        user_identifier = self.user.username if self.user else self.guest_email
        return f"{self.coupon.code} - {user_identifier} - {self.used_at}"
