from django.db import models
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

class Category(models.Model):
    name_en = models.CharField(_("Name (English)"), max_length=100)
    name_ar = models.CharField(_("Name (Arabic)"), max_length=100)
    slug = models.SlugField(unique=True)

    class Meta:
        verbose_name_plural = _("Categories")

    def __str__(self):
        return f"{self.name_en} / {self.name_ar}"

class Unit(models.Model):
    name_en = models.CharField(_("Name (English)"), max_length=50)
    name_ar = models.CharField(_("Name (Arabic)"), max_length=50)
    short_name = models.CharField(_("Short Name"), max_length=10)

    def __str__(self):
        return f"{self.name_en} / {self.name_ar}"

class Product(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="products")
    unit = models.ForeignKey(Unit, on_delete=models.SET_NULL, null=True, blank=True, related_name="products")
    supplier = models.ForeignKey('Supplier', on_delete=models.SET_NULL, null=True, blank=True, related_name="products")
    name_en = models.CharField(_("Name (English)"), max_length=200)
    name_ar = models.CharField(_("Name (Arabic)"), max_length=200)
    sku = models.CharField(_("Barcode/SKU"), max_length=50, unique=True)
    description = models.TextField(_("Description"), blank=True)
    cost_price = models.DecimalField(_("Cost Price"), max_digits=12, decimal_places=3, default=0)
    price = models.DecimalField(_("Sale Price"), max_digits=12, decimal_places=3)
    vat = models.DecimalField(_("VAT (%)"), max_digits=5, decimal_places=2, default=0)
    opening_stock = models.DecimalField(_("Opening Stock"), max_digits=15, decimal_places=2, default=0)
    stock_quantity = models.DecimalField(_("In Stock"), max_digits=15, decimal_places=2, default=0)
    min_stock_level = models.DecimalField(_("Stock Level (Alert)"), max_digits=15, decimal_places=2, default=0)
    has_expiry = models.BooleanField(_("Has Expiry Date"), default=False)
    expiry_date = models.DateField(_("Expiry Date"), null=True, blank=True)
    image = models.ImageField(_("Product Image"), upload_to="product_images/", blank=True, null=True)
    is_active = models.BooleanField(_("Active"), default=True)
    created_at = models.DateTimeField(auto_now_add=True)

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

class LoyaltyTier(models.Model):
    name_en = models.CharField(_("Name (English)"), max_length=50)
    name_ar = models.CharField(_("Name (Arabic)"), max_length=50)
    min_points = models.PositiveIntegerField(_("Minimum Points"), default=0)
    point_multiplier = models.DecimalField(_("Point Multiplier"), max_digits=4, decimal_places=2, default=1.0)
    discount_percentage = models.DecimalField(_("Discount Percentage"), max_digits=5, decimal_places=2, default=0)
    color_code = models.CharField(_("Color Code"), max_length=20, default="#6c757d")

    def __str__(self):
        return f"{self.name_en} / {self.name_ar}"

class Customer(models.Model):
    name = models.CharField(_("Name"), max_length=200)
    phone = models.CharField(_("Phone"), max_length=20, blank=True)
    email = models.EmailField(_("Email"), blank=True)
    address = models.TextField(_("Address"), blank=True)
    loyalty_points = models.DecimalField(_("Loyalty Points"), max_digits=15, decimal_places=2, default=0)
    loyalty_tier = models.ForeignKey(LoyaltyTier, on_delete=models.SET_NULL, null=True, blank=True, related_name="customers")

    def __str__(self):
        return self.name

    def update_tier(self):
        tiers = LoyaltyTier.objects.filter(min_points__lte=self.loyalty_points).order_by('-min_points')
        if tiers.exists():
            self.loyalty_tier = tiers.first()
            self.save()

class LoyaltyTransaction(models.Model):
    TRANSACTION_TYPES = [
        ('earned', _('Earned')),
        ('redeemed', _('Redeemed')),
        ('adjusted', _('Adjusted')),
    ]
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="loyalty_transactions")
    sale = models.ForeignKey('Sale', on_delete=models.SET_NULL, null=True, blank=True, related_name="loyalty_transactions")
    transaction_type = models.CharField(_("Type"), max_length=20, choices=TRANSACTION_TYPES)
    points = models.DecimalField(_("Points"), max_digits=15, decimal_places=2)
    notes = models.TextField(_("Notes"), blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.transaction_type} {self.points} for {self.customer.name}"

class Supplier(models.Model):
    name = models.CharField(_("Name"), max_length=200)
    contact_person = models.CharField(_("Contact Person"), max_length=200, blank=True)
    phone = models.CharField(_("Phone"), max_length=20, blank=True)

    def __str__(self):
        return self.name

class PaymentMethod(models.Model):
    name_en = models.CharField(_("Name (English)"), max_length=50)
    name_ar = models.CharField(_("Name (Arabic)"), max_length=50)
    is_active = models.BooleanField(_("Active"), default=True)

    def __str__(self):
        return f"{self.name_en} / {self.name_ar}"

class ExpenseCategory(models.Model):
    accounting_account = models.ForeignKey('accounting.Account', on_delete=models.SET_NULL, null=True, blank=True, related_name='expense_categories')
    name_en = models.CharField(_("Name (English)"), max_length=100)
    name_ar = models.CharField(_("Name (Arabic)"), max_length=100)
    description = models.TextField(_("Description"), blank=True)

    class Meta:
        verbose_name_plural = _("Expense Categories")

    def __str__(self):
        return f"{self.name_en} / {self.name_ar}"

class Expense(models.Model):
    category = models.ForeignKey(ExpenseCategory, on_delete=models.CASCADE, related_name="expenses")
    amount = models.DecimalField(_("Amount"), max_digits=15, decimal_places=3)
    date = models.DateField(_("Date"), default=timezone.now)
    description = models.TextField(_("Description"), blank=True)
    payment_method = models.ForeignKey(PaymentMethod, on_delete=models.SET_NULL, null=True, blank=True, related_name="expenses")
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="expenses")
    attachment = models.FileField(_("Attachment"), upload_to="expense_attachments/", blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Expense {self.id} - {self.amount} ({self.category.name_en})"

class Sale(models.Model):
    PAYMENT_TYPE_CHOICES = [
        ('cash', _('Cash')),
        ('credit', _('Credit')),
        ('partial', _('Partial')),
    ]
    STATUS_CHOICES = [
        ('paid', _('Paid')),
        ('partial', _('Partial')),
        ('unpaid', _('Unpaid')),
    ]
    
    customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True, blank=True, related_name="sales")
    quotation = models.ForeignKey('Quotation', on_delete=models.SET_NULL, null=True, blank=True, related_name="converted_sale")
    invoice_number = models.CharField(_("Invoice Number"), max_length=50, blank=True)
    subtotal = models.DecimalField(_("Subtotal"), max_digits=15, decimal_places=3, default=0)
    vat_amount = models.DecimalField(_("VAT Amount"), max_digits=15, decimal_places=3, default=0)
    total_amount = models.DecimalField(_("Total Amount"), max_digits=15, decimal_places=3)
    paid_amount = models.DecimalField(_("Paid Amount"), max_digits=15, decimal_places=3, default=0)
    balance_due = models.DecimalField(_("Balance Due"), max_digits=15, decimal_places=3, default=0)
    discount = models.DecimalField(_("Discount"), max_digits=15, decimal_places=3, default=0)
    loyalty_points_redeemed = models.DecimalField(_("Loyalty Points Redeemed"), max_digits=15, decimal_places=2, default=0)
    loyalty_discount_amount = models.DecimalField(_("Loyalty Discount"), max_digits=15, decimal_places=3, default=0)
    payment_type = models.CharField(_("Payment Type"), max_length=20, choices=PAYMENT_TYPE_CHOICES, default='cash')
    status = models.CharField(_("Status"), max_length=20, choices=STATUS_CHOICES, default='paid')
    due_date = models.DateField(_("Due Date"), null=True, blank=True)
    notes = models.TextField(_("Notes"), blank=True)
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="sales")
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Sale #{self.id} - {self.customer.name if self.customer else 'Guest'}"

    def update_balance(self):
        payments_total = self.payments.aggregate(total=models.Sum('amount'))['total'] or 0
        self.paid_amount = payments_total
        self.balance_due = self.total_amount - self.paid_amount
        if self.balance_due <= 0:
            self.status = 'paid'
        elif self.paid_amount > 0:
            self.status = 'partial'
        else:
            self.status = 'unpaid'
        self.save()

class SaleItem(models.Model):
    sale = models.ForeignKey(Sale, on_delete=models.CASCADE, related_name="items")
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.DecimalField(_("Quantity"), max_digits=15, decimal_places=2)
    unit_price = models.DecimalField(_("Unit Price"), max_digits=12, decimal_places=3)
    line_total = models.DecimalField(_("Line Total"), max_digits=15, decimal_places=3)

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

class SalePayment(models.Model):
    sale = models.ForeignKey(Sale, on_delete=models.CASCADE, related_name="payments")
    amount = models.DecimalField(_("Amount"), max_digits=15, decimal_places=3)
    payment_date = models.DateField(_("Payment Date"), default=timezone.now)
    payment_method = models.ForeignKey(PaymentMethod, on_delete=models.SET_NULL, null=True, blank=True, related_name="sale_payments")
    payment_method_name = models.CharField(_("Payment Method Name"), max_length=50, default="Cash") # Fallback
    notes = models.TextField(_("Notes"), blank=True)
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="sale_payments")

    def __str__(self):
        return f"Payment of {self.amount} for Sale #{self.sale.id}"

class Quotation(models.Model):
    STATUS_CHOICES = [
        ('draft', _('Draft')),
        ('sent', _('Sent')),
        ('accepted', _('Accepted')),
        ('rejected', _('Rejected')),
        ('converted', _('Converted to Invoice')),
    ]
    
    customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True, blank=True, related_name="quotations")
    quotation_number = models.CharField(_("Quotation Number"), max_length=50, blank=True)
    total_amount = models.DecimalField(_("Total Amount"), max_digits=15, decimal_places=3)
    discount = models.DecimalField(_("Discount"), max_digits=15, decimal_places=3, default=0)
    status = models.CharField(_("Status"), max_length=20, choices=STATUS_CHOICES, default='draft')
    valid_until = models.DateField(_("Valid Until"), null=True, blank=True)
    terms_and_conditions = models.TextField(_("Terms and Conditions"), blank=True)
    notes = models.TextField(_("Notes"), blank=True)
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="quotations")
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Quotation #{self.id} - {self.customer.name if self.customer else 'Guest'}"

class QuotationItem(models.Model):
    quotation = models.ForeignKey(Quotation, on_delete=models.CASCADE, related_name="items")
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.DecimalField(_("Quantity"), max_digits=15, decimal_places=2)
    unit_price = models.DecimalField(_("Unit Price"), max_digits=12, decimal_places=3)
    line_total = models.DecimalField(_("Line Total"), max_digits=15, decimal_places=3)

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

class Purchase(models.Model):
    PAYMENT_TYPE_CHOICES = [
        ('cash', _('Cash')),
        ('credit', _('Credit')),
        ('partial', _('Partial')),
    ]
    STATUS_CHOICES = [
        ('paid', _('Paid')),
        ('partial', _('Partial')),
        ('unpaid', _('Unpaid')),
    ]
    
    supplier = models.ForeignKey(Supplier, on_delete=models.SET_NULL, null=True, related_name="purchases")
    invoice_number = models.CharField(_("Invoice Number"), max_length=50, blank=True)
    total_amount = models.DecimalField(_("Total Amount"), max_digits=15, decimal_places=3)
    paid_amount = models.DecimalField(_("Paid Amount"), max_digits=15, decimal_places=3, default=0)
    balance_due = models.DecimalField(_("Balance Due"), max_digits=15, decimal_places=3, default=0)
    payment_type = models.CharField(_("Payment Type"), max_length=20, choices=PAYMENT_TYPE_CHOICES, default='cash')
    status = models.CharField(_("Status"), max_length=20, choices=STATUS_CHOICES, default='paid')
    due_date = models.DateField(_("Due Date"), null=True, blank=True)
    notes = models.TextField(_("Notes"), blank=True)
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="purchases")
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Purchase #{self.id} - {self.supplier.name if self.supplier else 'N/A'}"

    def update_balance(self):
        payments_total = self.payments.aggregate(total=models.Sum('amount'))['total'] or 0
        self.paid_amount = payments_total
        self.balance_due = self.total_amount - self.paid_amount
        if self.balance_due <= 0:
            self.status = 'paid'
        elif self.paid_amount > 0:
            self.status = 'partial'
        else:
            self.status = 'unpaid'
        self.save()

class PurchaseItem(models.Model):
    purchase = models.ForeignKey(Purchase, on_delete=models.CASCADE, related_name="items")
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.DecimalField(_("Quantity"), max_digits=15, decimal_places=2)
    cost_price = models.DecimalField(_("Cost Price"), max_digits=12, decimal_places=3)
    expiry_date = models.DateField(_("Expiry Date"), null=True, blank=True)
    line_total = models.DecimalField(_("Line Total"), max_digits=15, decimal_places=3)

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

class PurchasePayment(models.Model):
    purchase = models.ForeignKey(Purchase, on_delete=models.CASCADE, related_name="payments")
    amount = models.DecimalField(_("Amount"), max_digits=15, decimal_places=3)
    payment_date = models.DateField(_("Payment Date"), default=timezone.now)
    payment_method = models.ForeignKey(PaymentMethod, on_delete=models.SET_NULL, null=True, blank=True, related_name="purchase_payments")
    payment_method_name = models.CharField(_("Payment Method Name"), max_length=50, default="Cash") # Fallback
    notes = models.TextField(_("Notes"), blank=True)
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="purchase_payments")

    def __str__(self):
        return f"Payment of {self.amount} for Purchase #{self.purchase.id}"

class SaleReturn(models.Model):
    sale = models.ForeignKey(Sale, on_delete=models.SET_NULL, null=True, blank=True, related_name="returns")
    customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True, blank=True, related_name="sale_returns")
    return_number = models.CharField(_("Return Number"), max_length=50, blank=True)
    total_amount = models.DecimalField(_("Total Amount"), max_digits=15, decimal_places=3)
    notes = models.TextField(_("Notes"), blank=True)
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="sale_returns")
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Sale Return #{self.id} - {self.customer.name if self.customer else 'Guest'}"

class SaleReturnItem(models.Model):
    sale_return = models.ForeignKey(SaleReturn, on_delete=models.CASCADE, related_name="items")
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.DecimalField(_("Quantity"), max_digits=15, decimal_places=2)
    unit_price = models.DecimalField(_("Unit Price"), max_digits=12, decimal_places=3)
    line_total = models.DecimalField(_("Line Total"), max_digits=15, decimal_places=3)

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

class PurchaseReturn(models.Model):
    purchase = models.ForeignKey(Purchase, on_delete=models.SET_NULL, null=True, blank=True, related_name="returns")
    supplier = models.ForeignKey(Supplier, on_delete=models.SET_NULL, null=True, blank=True, related_name="purchase_returns")
    return_number = models.CharField(_("Return Number"), max_length=50, blank=True)
    total_amount = models.DecimalField(_("Total Amount"), max_digits=15, decimal_places=3)
    notes = models.TextField(_("Notes"), blank=True)
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="purchase_returns")
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Purchase Return #{self.id} - {self.supplier.name if self.supplier else 'N/A'}"

class PurchaseReturnItem(models.Model):
    purchase_return = models.ForeignKey(PurchaseReturn, on_delete=models.CASCADE, related_name="items")
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.DecimalField(_("Quantity"), max_digits=15, decimal_places=2)
    cost_price = models.DecimalField(_("Cost Price"), max_digits=12, decimal_places=3)
    expiry_date = models.DateField(_("Expiry Date"), null=True, blank=True)
    line_total = models.DecimalField(_("Line Total"), max_digits=15, decimal_places=3)

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

class HeldSale(models.Model):
    customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True, blank=True, related_name="held_sales")
    cart_data = models.JSONField(_("Cart Data"))
    total_amount = models.DecimalField(_("Total Amount"), max_digits=15, decimal_places=3)
    notes = models.TextField(_("Notes"), blank=True)
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="held_sales")
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Held Sale #{self.id} - {self.created_at.strftime('%Y-%m-%d %H:%M')}"

class SystemSetting(models.Model):
    business_name = models.CharField(_("Business Name"), max_length=200, default="Meezan Accounting")
    address = models.TextField(_("Address"), blank=True)
    phone = models.CharField(_("Phone"), max_length=20, blank=True)
    email = models.EmailField(_("Email"), blank=True)
    currency_symbol = models.CharField(_("Currency Symbol"), max_length=10, default="OMR")
    tax_rate = models.DecimalField(_("Tax Rate (%)"), max_digits=5, decimal_places=2, default=0)
    decimal_places = models.PositiveSmallIntegerField(_("Decimal Places"), default=3)
    logo = models.ImageField(_("Logo"), upload_to="business_logos/", blank=True, null=True)
    vat_number = models.CharField(_("VAT Number"), max_length=50, blank=True)
    registration_number = models.CharField(_("Registration Number"), max_length=50, blank=True)
    
    # Loyalty Settings
    loyalty_enabled = models.BooleanField(_("Enable Loyalty System"), default=False)
    points_per_currency = models.DecimalField(_("Points Earned per Currency Unit"), max_digits=10, decimal_places=2, default=1.0)
    currency_per_point = models.DecimalField(_("Currency Value per Point"), max_digits=10, decimal_places=3, default=0.010)
    min_points_to_redeem = models.PositiveIntegerField(_("Minimum Points to Redeem"), default=100)
    
    # WhatsApp (Wablas) Settings
    wablas_enabled = models.BooleanField(_("Enable WhatsApp Gateway"), default=False)
    wablas_token = models.CharField(_("Wablas API Token"), max_length=255, blank=True)
    wablas_server_url = models.URLField(_("Wablas Server URL"), blank=True, help_text="Example: https://console.wablas.com")
    wablas_secret_key = models.CharField(_("Wablas Secret Key"), max_length=255, blank=True)

    def __str__(self):
        return self.business_name


class Device(models.Model):
    DEVICE_TYPES = [
        ('printer', _('Printer')),
        ('scanner', _('Scanner')),
        ('scale', _('Weight Scale')),
        ('display', _('Customer Display')),
        ('other', _('Other')),
    ]
    CONNECTION_TYPES = [
        ('network', _('Network (IP)')),
        ('usb', _('USB')),
        ('bluetooth', _('Bluetooth')),
    ]

    name = models.CharField(_("Device Name"), max_length=100)
    device_type = models.CharField(_("Device Type"), max_length=20, choices=DEVICE_TYPES)
    connection_type = models.CharField(_("Connection Type"), max_length=20, choices=CONNECTION_TYPES, default='network')
    ip_address = models.GenericIPAddressField(_("IP Address"), blank=True, null=True)
    port = models.PositiveIntegerField(_("Port"), blank=True, null=True)
    is_active = models.BooleanField(_("Active"), default=True)
    config_json = models.JSONField(_("Configuration"), blank=True, null=True, help_text=_("Additional driver configuration in JSON format"))
    created_at = models.DateTimeField(auto_now_add=True)

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

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
    image = models.ImageField(_("Profile Picture"), upload_to="profile_pics/", blank=True, null=True)
    phone = models.CharField(_("Phone Number"), max_length=20, blank=True)
    bio = models.TextField(_("Bio"), blank=True)

    def __str__(self):
        return self.user.username

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    if not hasattr(instance, 'profile'):
        UserProfile.objects.create(user=instance)
    instance.profile.save()