"""
Order Management Models
"""
from django.db import models
from django.conf import settings
from products.models import Product, ProductVariation
from accounts.models import Address
from django.core.validators import RegexValidator


class CourierCompany(models.Model):
    """Courier Services for Shipping"""
    name = models.CharField(max_length=100)
    tracking_url_base = models.CharField(
        max_length=255, 
        blank=True, 
        help_text="Base URL for tracking (e.g., https://track.com?id=)"
    )
    website = models.URLField(blank=True)
    contact_number = models.CharField(max_length=50, blank=True)
    is_active = models.BooleanField(default=True)
    
    class Meta:
        verbose_name_plural = "Courier Companies"
        ordering = ['name']

    def __str__(self):
        return self.name


class Order(models.Model):
    """Customer Orders"""
    
    class OrderStatus(models.TextChoices):
        PENDING = 'PENDING', 'Pending'
        CONFIRMED = 'CONFIRMED', 'Confirmed'
        PROCESSING = 'PROCESSING', 'Processing'
        SHIPPED = 'SHIPPED', 'Shipped'
        DELIVERED = 'DELIVERED', 'Delivered'
        CANCELLED = 'CANCELLED', 'Cancelled'
        REFUNDED = 'REFUNDED', 'Refunded'
    
    # Order Information
    order_number = models.CharField(max_length=50, unique=True)
    order_code = models.CharField(
        max_length=20,
        unique=True,
        blank=True,
        null=True,
        validators=[RegexValidator(regex=r'^[A-Z]{2}\d{8}$', message='Order code must be 2 uppercase letters followed by 8 digits')]
    )
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='orders'
    )
    
    # Shipping Information
    shipping_address = models.ForeignKey(
        Address,
        on_delete=models.SET_NULL,
        null=True,
        related_name='shipping_orders'
    )
    billing_address = models.ForeignKey(
        Address,
        on_delete=models.SET_NULL,
        null=True,
        related_name='billing_orders'
    )
    
    # Pricing
    subtotal = models.DecimalField(max_digits=10, decimal_places=2)
    tax = models.DecimalField(max_digits=10, decimal_places=2, default=0)
    shipping_cost = models.DecimalField(max_digits=10, decimal_places=2, default=0)
    discount = models.DecimalField(max_digits=10, decimal_places=2, default=0)
    total = models.DecimalField(max_digits=10, decimal_places=2)
    
    # Status
    status = models.CharField(
        max_length=20,
        choices=OrderStatus.choices,
        default=OrderStatus.PENDING
    )
    
    # Payment
    is_paid = models.BooleanField(default=False)
    payment_method = models.CharField(max_length=50, blank=True)
    payment_id = models.CharField(max_length=255, blank=True)
    
    # Tracking
    courier_company = models.ForeignKey(
        CourierCompany,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='orders'
    )
    tracking_number = models.CharField(max_length=100, blank=True)
    
    # Notes
    customer_notes = models.TextField(blank=True)
    staff_notes = models.TextField(blank=True)
    
    # Timestamps
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    delivered_at = models.DateTimeField(null=True, blank=True)
    
    class Meta:
        ordering = ['-created_at']
        
    def __str__(self):
        return self.order_code or self.order_number
        
    def save(self, *args, **kwargs):
        if not self.order_code:
            import random
            import string
            # Generate valid order code: 2 uppercase letters + 8 digits
            # Loop until unique
            for _ in range(10):
                prefix = ''.join(random.choices(string.ascii_uppercase, k=2))
                digits = ''.join(random.choices(string.digits, k=8))
                code = f"{prefix}{digits}"
                if not self.__class__.objects.filter(order_code=code).exists():
                    self.order_code = code
                    break
            
            # Fallback if loop fails (unlikely)
            if not self.order_code:
                import uuid
                self.order_code = str(uuid.uuid4()).upper()[:10]

        if not self.order_number:
            if self.order_code:
                self.order_number = self.order_code
            else:
                import uuid
                self.order_number = str(uuid.uuid4())

        super().save(*args, **kwargs)


class OrderItem(models.Model):
    """Individual items in an order"""
    
    order = models.ForeignKey(
        Order,
        on_delete=models.CASCADE,
        related_name='items'
    )
    product = models.ForeignKey(
        Product,
        on_delete=models.CASCADE
    )
    variation = models.ForeignKey(
        ProductVariation,
        on_delete=models.SET_NULL,
        null=True,
        blank=True
    )
    
    # Snapshot of product details at time of order
    product_name = models.CharField(max_length=300)
    product_sku = models.CharField(max_length=100)
    unit_price = models.DecimalField(max_digits=10, decimal_places=2)
    quantity = models.IntegerField()
    total_price = models.DecimalField(max_digits=10, decimal_places=2)
    status = models.CharField(max_length=20, choices=Order.OrderStatus.choices, default=Order.OrderStatus.PENDING)
    
    # Tracking per item (for multi-vendor)
    courier_company = models.ForeignKey(
        CourierCompany,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='order_items'
    )
    tracking_number = models.CharField(max_length=100, blank=True)
    shipped_at = models.DateTimeField(null=True, blank=True)
    delivered_at = models.DateTimeField(null=True, blank=True)
    
    created_at = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        ordering = ['id']
    
    def __str__(self):
        return f"{self.product_name} x {self.quantity}"


class OrderStatusHistory(models.Model):
    """Track order status changes"""
    
    order = models.ForeignKey(
        Order,
        on_delete=models.CASCADE,
        related_name='status_history'
    )
    status = models.CharField(max_length=20, choices=Order.OrderStatus.choices)
    notes = models.TextField(blank=True)
    changed_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True
    )
    created_at = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        ordering = ['-created_at']
        verbose_name_plural = 'Order Status Histories'
    
    def __str__(self):
        return f"{self.order.order_number} - {self.status}"
