
from django import forms
from django.utils.timezone import now
from .models import Product, Category, Batch, ProductImage
from .widgets import MultiFileInput
from django.apps import apps


# Category Form
class CategoryForm(forms.ModelForm):
    class Meta:
        model = Category
        fields = ['name', 'parent', 'description', 'thumbnail']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.instance.pk:
            self.fields['parent'].queryset = Category.objects.exclude(pk=self.instance.pk)

    def clean(self):
        cleaned_data = super().clean()
        parent = cleaned_data.get('parent')
        if parent:
            if parent == self.instance:
                raise forms.ValidationError("A category cannot be its own parent.")
        return cleaned_data


# Product Form
class ProductForm(forms.ModelForm):
    image = forms.ImageField(required=False, label="Primary Image")
    images = forms.FileField(
        widget=MultiFileInput(attrs={'multiple': True}),
        required=False,
        label="Additional Images"
    )

    class Meta:
        model = Product
        fields = [
            'name', 'barcode', 'buying_price', 'selling_price',
            'stock_quantity', 'low_stock_threshold', 'packaging_type', 'expiry_date',
            'category', 'description', 'is_active', 'image'
        ]

    def clean_low_stock_threshold(self):
        low_stock_threshold = self.cleaned_data.get('low_stock_threshold')
        if low_stock_threshold is not None and low_stock_threshold < 0:
            raise forms.ValidationError("Low stock threshold cannot be negative.")
        return low_stock_threshold or 0

    def clean_expiry_date(self):
        expiry_date = self.cleaned_data.get('expiry_date')
        if expiry_date and expiry_date < now().date():
            raise forms.ValidationError("Expiry date cannot be in the past.")
        return expiry_date

    def clean(self):
        cleaned_data = super().clean()
        buying_price = cleaned_data.get('buying_price')
        selling_price = cleaned_data.get('selling_price')

        if buying_price is not None and selling_price is not None and selling_price <= buying_price:
            self.add_error('selling_price', "Selling price must be greater than buying price.")
        return cleaned_data

    def save(self, commit=True):
        instance = super().save(commit=False)

        if commit:
            instance.save()

            # Handle primary image
            if self.cleaned_data.get('image'):
                if not ProductImage.objects.filter(product=instance, is_primary=True).exists():
                    ProductImage.objects.create(product=instance, image=self.cleaned_data['image'], is_primary=True)

            # Handle additional images
            images = self.files.getlist('images')
            for image in images:
                ProductImage.objects.create(product=instance, image=image)

        return instance


# Batch Form
class BatchForm(forms.ModelForm):
    class Meta:
        model = Batch
        fields = [
            'product', 'batch_code', 'quantity', 'buying_price',
            'selling_price', 'expiry_date', 'supplier', 'notes'
        ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        for field in self.fields.values():
            field.widget.attrs.update({'class': 'form-control'})

        self.fields['product'].widget.attrs.update({'placeholder': '-- Select a Product --'})
        self.fields['batch_code'].widget.attrs.update({'placeholder': 'Enter batch code (optional)'})
        self.fields['quantity'].widget.attrs.update({'placeholder': 'Enter quantity received'})
        self.fields['buying_price'].widget.attrs.update({'placeholder': 'Enter buying price per unit'})
        self.fields['selling_price'].widget.attrs.update({'placeholder': 'Enter selling price per unit'})
        self.fields['expiry_date'].widget.attrs.update({'type': 'date'})
        self.fields['notes'].widget.attrs.update({'placeholder': 'Add any additional notes (optional)'})

    def clean_quantity(self):
        quantity = self.cleaned_data.get('quantity')
        if quantity is None or quantity <= 0:
            raise forms.ValidationError("Quantity must be greater than 0.")
        return quantity

    def clean_buying_price(self):
        buying_price = self.cleaned_data.get('buying_price')
        if buying_price is None or buying_price <= 0:
            raise forms.ValidationError("Buying price must be greater than 0.")
        return buying_price

    def clean_selling_price(self):
        selling_price = self.cleaned_data.get('selling_price')
        buying_price = self.cleaned_data.get('buying_price')

        if selling_price is None or selling_price <= 0:
            raise forms.ValidationError("Selling price must be greater than 0.")
        if buying_price and selling_price <= buying_price:
            raise forms.ValidationError("Selling price must be greater than the buying price.")
        return selling_price

    def clean_supplier(self):
        supplier = self.cleaned_data.get('supplier')
        if supplier:
            Supplier = apps.get_model('suppliers', 'Supplier')
            if not Supplier.objects.filter(pk=supplier.pk, is_active=True).exists():
                raise forms.ValidationError("The selected supplier is inactive or invalid.")
        return supplier

    def clean_expiry_date(self):
        expiry_date = self.cleaned_data.get('expiry_date')
        if expiry_date and expiry_date < forms.datetime.date.today():
            raise forms.ValidationError("Expiry date cannot be in the past.")
        return expiry_date

# Product Import Form
class ProductImportForm(forms.Form):
    imported_file = forms.FileField(
        label='Upload CSV or Excel File',
        widget=forms.FileInput(attrs={'accept': '.csv,.xlsx'}),
        required=True
    )

    def clean_imported_file(self):
        file = self.cleaned_data.get('imported_file')
        if not file.name.endswith(('.csv', '.xlsx')):
            raise forms.ValidationError("Only CSV or Excel files are supported.")
        if file.size > 5 * 1024 * 1024:
            raise forms.ValidationError("File size should not exceed 5MB.")
        return file
