from django.db import models
import uuid


class Brand(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    company = models.ForeignKey("accounts.Company", on_delete=models.CASCADE, db_constraint=False, related_name="brands")
    name = models.CharField(max_length=255)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "brands"
        unique_together = ["company", "name"]
        ordering = ["name"]

    def __str__(self):
        return self.name


class ProductCategory(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    company = models.ForeignKey("accounts.Company", on_delete=models.CASCADE, db_constraint=False, related_name="categories")
    name = models.CharField(max_length=255)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "product_categories"
        unique_together = ["company", "name"]
        ordering = ["name"]
        verbose_name_plural = "Product Categories"

    def __str__(self):
        return self.name


class ProductSize(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    company = models.ForeignKey("accounts.Company", on_delete=models.CASCADE, db_constraint=False, related_name="sizes")
    name = models.CharField(max_length=100, help_text="e.g. 1kg, 500ml, XL, 12x12 inch")

    class Meta:
        db_table = "product_sizes"
        unique_together = ["company", "name"]
        ordering = ["name"]

    def __str__(self):
        return self.name


class Supplier(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    company = models.ForeignKey("accounts.Company", on_delete=models.CASCADE, db_constraint=False, related_name="suppliers")
    name = models.CharField(max_length=255)
    phone = models.CharField(max_length=20, blank=True)
    email = models.EmailField(blank=True)
    address = models.TextField(blank=True)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "suppliers"
        ordering = ["name"]

    def __str__(self):
        return self.name


class Product(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    company = models.ForeignKey("accounts.Company", on_delete=models.CASCADE, db_constraint=False, related_name="products")
    brand = models.ForeignKey(Brand, on_delete=models.SET_NULL, null=True, blank=True, related_name="products")
    category = models.ForeignKey(ProductCategory, on_delete=models.SET_NULL, null=True, blank=True, related_name="products")
    size = models.ForeignKey(ProductSize, on_delete=models.SET_NULL, null=True, blank=True, related_name="products")
    name = models.CharField(max_length=255)
    sku = models.CharField(max_length=100, blank=True, help_text="Optional product code")
    buy_price = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    sell_price = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    current_stock = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    min_stock_alert = models.DecimalField(max_digits=12, decimal_places=2, default=10)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "products"
        ordering = ["name"]
        indexes = [
            models.Index(fields=["company", "is_active"]),
            models.Index(fields=["company", "brand"]),
            models.Index(fields=["company", "category"]),
        ]

    def __str__(self):
        return self.name

    @property
    def stock_value(self):
        return self.current_stock * self.buy_price


class Purchase(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    company = models.ForeignKey("accounts.Company", on_delete=models.CASCADE, db_constraint=False, related_name="purchases")
    supplier = models.ForeignKey(Supplier, on_delete=models.SET_NULL, null=True, blank=True, related_name="purchases")
    branch = models.ForeignKey(
        "accounts.Branch", on_delete=models.DO_NOTHING, null=True, blank=True,
        db_constraint=False, related_name="+",
        help_text="Branch this record belongs to. Empty = legacy row (treated as main branch).",
    )
    invoice_number = models.CharField(max_length=255, unique=True)
    date = models.DateField()
    total_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    discount = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    net_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    notes = models.TextField(blank=True)
    created_by = models.ForeignKey("accounts.CustomUser", on_delete=models.SET_NULL, db_constraint=False, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "purchases"
        ordering = ["-date", "-created_at"]
        indexes = [
            models.Index(fields=["company", "date"]),
            models.Index(fields=["company", "branch", "date"]),
        ]

    def __str__(self):
        return self.invoice_number


class PurchaseItem(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    purchase = models.ForeignKey(Purchase, on_delete=models.CASCADE, related_name="items")
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="purchase_items")
    quantity = models.DecimalField(max_digits=12, decimal_places=2)
    buy_price = models.DecimalField(max_digits=12, decimal_places=2)
    total = models.DecimalField(max_digits=12, decimal_places=2)

    class Meta:
        db_table = "purchase_items"

    def __str__(self):
        return f"{self.purchase.invoice_number} - {self.product.name}"


class StockLog(models.Model):
    STOCK_TYPE_CHOICES = (
        ("purchase", "Purchase"),
        ("purchase_return", "Purchase Return"),
        ("sale", "Sale"),
        ("sale_return", "Sale Return"),
        ("adjustment", "Manual Adjustment"),
    )
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    company = models.ForeignKey("accounts.Company", on_delete=models.CASCADE, db_constraint=False, related_name="stock_logs")
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="stock_logs")
    branch = models.ForeignKey(
        "accounts.Branch", on_delete=models.DO_NOTHING, null=True, blank=True,
        db_constraint=False, related_name="+",
        help_text="Branch this record belongs to. Empty = legacy row (treated as main branch).",
    )
    stock_type = models.CharField(max_length=20, choices=STOCK_TYPE_CHOICES)
    quantity_change = models.DecimalField(max_digits=12, decimal_places=2, help_text="Positive = stock in, negative = stock out")
    reference_id = models.CharField(max_length=255, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "stock_logs"
        ordering = ["-created_at"]

    def __str__(self):
        return f"{self.product.name} ({self.quantity_change})"


class BranchStock(models.Model):
    """Stock of one product held by one branch.

    ``Product.current_stock`` stays as the company-wide total (sum of all branch
    rows) so existing screens keep working; every stock movement goes through
    ``inventory.stock.apply_stock_change`` which keeps both in sync.
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    company = models.ForeignKey("accounts.Company", on_delete=models.CASCADE, db_constraint=False, related_name="branch_stocks")
    branch = models.ForeignKey(
        "accounts.Branch", on_delete=models.DO_NOTHING, db_constraint=False, related_name="+",
    )
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="branch_stocks")
    quantity = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "branch_stocks"
        unique_together = [("branch", "product")]
        indexes = [
            models.Index(fields=["company", "branch"]),
        ]

    def __str__(self):
        return f"{self.product.name} @ {self.branch_id}: {self.quantity}"
