from django.db import models
from django.utils.translation import gettext_lazy as _
from datetime import date
from django.contrib.auth.models import User
from django.core.validators import MinValueValidator
from django.db.models import Sum, DecimalField
from django.db.models.functions import Coalesce
from decimal import Decimal
from projects.models import Project
    
# Product Category Model	
class ProductCategory(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True)
    
    def __str__(self):
        return self.name

# Product Material Type Model    
class MaterialType(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True)
    
    def __str__(self):
        return self.name

# Product Model    
class Product(models.Model):
    UNIT_CHOICES = [
        ('KG', 'KG'),
        ('MT', 'MT'),
        ('Pieces', 'Pieces'),
    ]

    name = models.CharField(max_length=255)
    product_code = models.CharField(max_length=50, unique=True, blank=True, null=True)
    material_type = models.ForeignKey(MaterialType, on_delete=models.SET_NULL, null=True)
    unit_of_measurement = models.CharField(max_length=10, choices=UNIT_CHOICES, default='KG')
    attachments = models.FileField(upload_to='product_attachments/', blank=True, null=True)
    description = models.TextField(blank=True, null=True)
    min_stock_level = models.PositiveIntegerField(default=0)

    def __str__(self):
        return f"{self.name} ({self.product_code})"
    
    @property
    def current_stock(self):
        """Calculates current stock from movements"""
        from django.db.models import Sum
        result = self.stock_movements.aggregate(
            total_in=Sum('quantity', filter=models.Q(movement_type='IN')),
            total_out=Sum('quantity', filter=models.Q(movement_type='OUT'))
        )
        total_in = result['total_in'] or 0
        total_out = result['total_out'] or 0
        return total_in - total_out

    @property
    def average_purchase_price(self):
        """Calculates weighted average purchase price"""
        incoming = self.stock_movements.filter(movement_type='IN').aggregate(
            total_value=Sum(models.F('quantity') * models.F('purchase_price')),
            total_quantity=Sum('quantity')
        )
        if incoming['total_quantity'] and incoming['total_value']:
            return incoming['total_value'] / incoming['total_quantity']
        return 0

# Warehouse Model
class Warehouse(models.Model):
    code = models.CharField(max_length=10, unique=True)
    name = models.CharField(max_length=100)
    location = models.CharField(max_length=200)
    is_active = models.BooleanField(default=True)
    
    def __str__(self):
        return f"{self.name} ({self.code})"

# Stock Movement Model
class StockMovement(models.Model):
    MOVEMENT_TYPES = [
        ('IN', 'Stock In'),
        ('OUT', 'Stock Out'),
        ('ADJ', 'Adjustment'),
        ('TRF', 'Transfer'),
    ]
    
    product = models.ForeignKey(Product, on_delete=models.PROTECT, related_name='stock_movements')
    warehouse = models.ForeignKey(Warehouse, on_delete=models.PROTECT)
    movement_type = models.CharField(max_length=5, choices=MOVEMENT_TYPES)
    quantity = models.DecimalField(max_digits=10, decimal_places=3, validators=[MinValueValidator(0.001)])
    purchase_price = models.DecimalField(
        max_digits=10, 
        decimal_places=2,
        null=True,
        blank=True,
        verbose_name="Purchase Price"
    )
    sale_price = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        null=True,
        blank=True,
        verbose_name="Sale Price"
    )
    reference = models.CharField(max_length=100, blank=True)  # PO number, invoice number, etc.
    notes = models.TextField(blank=True)
    date = models.DateTimeField(auto_now_add=True)
    # user = models.ForeignKey('auth.User', on_delete=models.PROTECT)
    constraints = [
        models.UniqueConstraint(
            fields=['product', 'reference', 'movement_type'],
            name='unique_stockmovement_product_ref_type'
        )
    ]
    def __str__(self):
        return f"{self.get_movement_type_display()} of {self.product} ({self.quantity})"
    
    class Meta:
        ordering = ['-date']
        verbose_name = "Stock Movement"
        verbose_name_plural = "Stock Movements"

    def decrease_stock(self, quantity):
        self.quantity -= quantity
        self.save()

    def increase_stock(self, quantity):
        self.quantity += quantity
        self.save()



class MaterialConsumption(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    date = models.DateField()
    remarks = models.TextField(blank=True)
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)

class MaterialConsumptionItem(models.Model):
    consumption = models.ForeignKey(MaterialConsumption, on_delete=models.CASCADE, related_name='items')
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.DecimalField(max_digits=10, decimal_places=2)
    unit_price = models.DecimalField(max_digits=10, decimal_places=2)
    