from PIL import Image
from django import forms
from django.apps import apps
from cms.models import *
from django.forms import CheckboxInput
from shops.models import *
from accounts.models import *
from products.models import *
from orders.models import *
from django.forms.models import inlineformset_factory
from ckeditor.widgets import CKEditorWidget  # type: ignore
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
import re
from decimal import Decimal, InvalidOperation
from django.core.validators import URLValidator




class MultiFileInput(forms.ClearableFileInput):
    def __init__(self, attrs=None):
        super().__init__(attrs)
        self.attrs['multiple'] = 'multiple'


class UserForm(forms.ModelForm):
    class Meta:
        model = Users
        fields = (
            "first_name",
            "last_name",
            "email",
            "user_type",
            "phone_number",
            "status",
        )

    first_name = forms.CharField(
        label="first_name",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )

    last_name = forms.CharField(
        label="last_name", widget=forms.TextInput(attrs={"class": "form-control"})
    )

    email = forms.EmailField(
        label="email", widget=forms.TextInput(attrs={"class": "form-control"})
    )

    user_type = forms.ChoiceField(
        choices=[
            ("Super Admin", "Super Admin"),
            ("NBC Admin", "NBC Admin"),
            ("Shop Admin", "Shop Admin"),
            ("PU Admin", "PU Admin"),
        ],
        widget=forms.Select(
            attrs={"class": "form-control form-select", "id": "user_type-select"}
        ),
    )

    phone_number = forms.CharField(
        label="phone_number", widget=forms.TextInput(attrs={"class": "form-control"})
    )
    status = forms.ChoiceField(
        choices=[("active", "Active"), ("inactive", "Inactive")],
        widget=forms.Select(
            attrs={"class": "form-control form-select", "id": "status-select"}
        ),
    )

    def clean_first_name(self):
        first_name = self.cleaned_data.get("first_name")
        if len(first_name) < 1 or len(first_name) > 50:
            raise forms.ValidationError(
                "First name must be between 1 and 50 characters long."
            )
        if not re.match(r"^[a-zA-Z\s\'-]+$", first_name):
            raise forms.ValidationError(
                "First name may only contain alphabets, spaces, hyphens, and apostrophes."
            )
        first_name = re.sub(r"\s+", " ", first_name)
        capitalize_first_name = first_name.capitalize()
        return capitalize_first_name

    def clean_last_name(self):
        last_name = self.cleaned_data.get("last_name")
        if len(last_name) < 1 or len(last_name) > 50:
            raise forms.ValidationError(
                "First name must be between 1 and 50 characters long."
            )
        if not re.match(r"^[a-zA-Z\s\'-]+$", last_name):
            raise forms.ValidationError(
                "First name may only contain alphabets, spaces, hyphens, and apostrophes."
            )
        last_name = re.sub(r"\s+", " ", last_name)
        capitalize_last_name = last_name.capitalize()
        return capitalize_last_name

    def clean_phone_number(self):
        phone_number = self.cleaned_data.get("phone_number")
        if not re.match(r"^\+?1?\d{9,15}$", phone_number):
            raise ValidationError(
                "Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed."
            )
        return phone_number


class UserEditForm(forms.ModelForm):
    class Meta:
        model = Users
        fields = (
            "first_name",
            "last_name",
            "email",
            "user_type",
            "phone_number",
            "status",
        )

    first_name = forms.CharField(
        label="first_name",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )

    last_name = forms.CharField(
        label="last_name", widget=forms.TextInput(attrs={"class": "form-control"})
    )

    email = forms.EmailField(
        label="email",
        widget=forms.TextInput(attrs={"class": "form-control", "readonly": "readonly"}),
    )
    user_type = forms.CharField(
        widget=forms.TextInput(
            attrs={
                "class": "form-control",
                "id": "user_type-select",
                "readonly": "readonly",
            }
        ),
    )

    phone_number = forms.CharField(
        label="phone_number", widget=forms.TextInput(attrs={"class": "form-control"})
    )
    status = forms.ChoiceField(
        choices=[("active", "Active"), ("inactive", "Inactive")],
        widget=forms.Select(
            attrs={"class": "form-control form-select", "id": "status-select"}
        ),
    )

    def clean_first_name(self):
        first_name = self.cleaned_data.get("first_name")
        if len(first_name) < 1 or len(first_name) > 50:
            raise forms.ValidationError(
                "First name must be between 1 and 50 characters long."
            )
        if not re.match(r"^[a-zA-Z\s\'-]+$", first_name):
            raise forms.ValidationError(
                "First name may only contain alphabets, spaces, hyphens, and apostrophes."
            )
        first_name = re.sub(r"\s+", " ", first_name)
        capitalize_first_name = first_name.capitalize()
        return capitalize_first_name

    def clean_last_name(self):
        last_name = self.cleaned_data.get("last_name")
        if len(last_name) < 1 or len(last_name) > 50:
            raise forms.ValidationError(
                "First name must be between 1 and 50 characters long."
            )
        if not re.match(r"^[a-zA-Z\s\'-]+$", last_name):
            raise forms.ValidationError(
                "First name may only contain alphabets, spaces, hyphens, and apostrophes."
            )
        last_name = re.sub(r"\s+", " ", last_name)
        capitalize_last_name = last_name.capitalize()
        return capitalize_last_name

    def clean_phone_number(self):
        phone_number = self.cleaned_data.get("phone_number")
        if not re.match(r"^\+?1?\d{9,15}$", phone_number):
            raise ValidationError(
                "Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed."
            )
        return phone_number


class ShopForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if args and args[0] is not None:
            data = args[0].copy()  # .copy() returns a mutable QueryDict
            data.setlist(
                'unit_admin_user',
                [v for v in data.getlist('unit_admin_user') if v.strip() != '']
            )
            self.data = data

    class Meta:
        model = Shop
        fields = (
            "unit_name",
            "unit_location",
            "unit_code",
            "unit_admin_user",
            "street",
            "city",
            "district",
            "state_or_province",
            "pin_code",
            "latitude",
            "longitude",
            "contact_no",
            "email",
            "gst",
            "delivery_mode",
            "delivery_radius",
            "status",
        )

    unit_name = forms.CharField(
        label="unit_name",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    unit_location = forms.CharField(
        label="unit_location",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    unit_code = forms.CharField(
        label="unit_code",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    unit_admin_user = forms.ModelMultipleChoiceField(
        queryset=Users.objects.filter(user_type="Shop Admin").all(),
        widget=forms.SelectMultiple(attrs={"class": "form-control", "size": "10"}),
        error_messages={"required": "Please select at least one shop admin user."},
    )
    street = forms.CharField(
        label="Street",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    city = forms.CharField(
        label="city",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    district = forms.CharField(
        label="District",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    state_or_province = forms.CharField(
        label="state",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    pin_code = forms.IntegerField(
        label="Pin Code",
        widget=forms.TextInput(attrs={"class": "form-control", "max_length": "6"}),
        required=True,
    )
    latitude = forms.CharField(
        label="latitude",
        widget=forms.TextInput(attrs={"class": "form-control", "readonly": "readonly"}),
        required=True,
    )
    longitude = forms.CharField(
        label="longitude",
        widget=forms.TextInput(attrs={"class": "form-control", "readonly": "readonly"}),
        required=True,
    )
    contact_no = forms.CharField(
        label="Contact Number",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=False,
    )
    email = forms.EmailField(
        label="Email ID",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=False,
    )
    gst = forms.CharField(
        label="GSTIN",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    delivery_mode = forms.ChoiceField(
        choices=[("Shop own", "Shop own"), ("Third party", "Third party")],
        widget=forms.Select(
            attrs={
                "class": "form-control form-select",
                "id": "delivery_mode_select",
            }
        ),
        required=True,
    )
    delivery_radius = forms.FloatField(
        label="Delivery Radius (km)",
        widget=forms.NumberInput(attrs={"class": "form-control"}),
        required=True,
        initial=0.0,
    )
    status = forms.ChoiceField(
        choices=[("Open", "Open"), ("Close", "Close")],
        widget=forms.Select(
            attrs={"class": "form-control form-select", "id": "status-select"}
        ),
        required=True,
    )

    def clean_unit_name(self):
        shop_name = self.cleaned_data.get("unit_name")
        if len(shop_name) < 3 or len(shop_name) > 120:
            raise forms.ValidationError(
                "Unit name must be between 3 and 120 characters long."
            )
        if not re.match(r"^[a-zA-Z0-9\s@.,-]+$", shop_name):
            raise forms.ValidationError(
                "Unit name may only contain alphabets, numerics, spaces, and some special characters like '@', '.', ',', and '-'."
            )
        if re.search(r"\s{2,}", shop_name):
            raise forms.ValidationError("Consecutive spaces not allowed")
        return shop_name

    def clean_gst(self):
        gst = self.cleaned_data.get("gst")
        if len(gst) != 15:
            raise forms.ValidationError("GSTIN must be 15 characters long.")
        gst_pattern = r"^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}Z[0-9A-Z]{1}$"
        if not re.match(gst_pattern, gst):
            raise forms.ValidationError("Invalid GSTIN format.")
        return gst

    def clean_contact_no(self):
        phone_number = self.cleaned_data.get("contact_no")
        # contact_no is required=False, allow empty
        if not phone_number:
            return phone_number
        if not re.match(r"^\+?1?\d{9,15}$", phone_number):
            raise ValidationError(
                "Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed."
            )
        return phone_number

    def clean_delivery_radius(self):
        delivery_radius = self.cleaned_data.get("delivery_radius")
        if delivery_radius < 0:
            raise forms.ValidationError("Delivery radius must be a positive number.")
        return delivery_radius

    def clean_unit_admin_user(self):
        unit_admin_user = self.cleaned_data.get("unit_admin_user")

        if not unit_admin_user:
            raise ValidationError("Please select at least one shop admin user.")

        # .distinct() prevents duplicate rows from M2M join
        shop_qs = Shop.objects.filter(
            unit_admin_user__in=unit_admin_user
        ).distinct()

        # Exclude current shop when editing (self.instance.pk is None on create)
        if self.instance and self.instance.pk:
            shop_qs = shop_qs.exclude(pk=self.instance.pk)

        if shop_qs.exists():
            users = []
            for admin in unit_admin_user:
                if shop_qs.filter(unit_admin_user=admin).exists():
                    users.append(f"{admin.first_name} {admin.last_name}")
            name_list = ", ".join(users)
            raise ValidationError(
                f"Shop Admin(s) {name_list} is already assigned to another shop."
            )

        return unit_admin_user


class BankDetailsForm(forms.ModelForm):
    class Meta:
        model = BankDetails
        fields = [
            "account_name",
            "bank_name",
            "branch_name",
            "ifsc_code",
            "account_number",
        ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["account_name"].widget.attrs.update({"class": "form-control"})
        self.fields["bank_name"].widget.attrs.update({"class": "form-control"})
        self.fields["branch_name"].widget.attrs.update({"class": "form-control"})
        self.fields["ifsc_code"].widget.attrs.update({"class": "form-control"})
        self.fields["account_number"].widget.attrs.update({"class": "form-control"})

    def clean_account_name(self):
        account_name = self.cleaned_data.get("account_name", "").strip()
        if len(account_name) < 1 or len(account_name) > 100:
            raise forms.ValidationError(
                "Account name must be between 1 and 100 characters long."
            )
        if not re.match(r"^[a-zA-Z\s\'-]+$", account_name):
            raise forms.ValidationError(
                "Account name can only contain alphabets, spaces, hyphens, and apostrophes."
            )
        return account_name

    def clean_bank_name(self):
        bank_name = self.cleaned_data.get("bank_name", "").strip()
        if len(bank_name) < 1 or len(bank_name) > 100:
            raise forms.ValidationError(
                "Bank name must be between 1 and 100 characters long."
            )
        if not re.match(r"^[a-zA-Z\s]+$", bank_name):
            raise forms.ValidationError(
                "Bank name can only contain alphabets and spaces."
            )
        return bank_name

    def clean_branch_name(self):
        branch_name = self.cleaned_data.get("branch_name", "").strip()
        if len(branch_name) < 1 or len(branch_name) > 100:
            raise forms.ValidationError(
                "Branch name must be between 1 and 100 characters long."
            )
        if not re.match(r"^[a-zA-Z\s]+$", branch_name):
            raise forms.ValidationError(
                "Branch name can only contain alphabets and spaces."
            )
        return branch_name

    def clean_ifsc_code(self):
        ifsc_code = self.cleaned_data.get("ifsc_code", "").strip()
        if len(ifsc_code) != 11:
            raise forms.ValidationError("IFSC code must be exactly 11 characters long.")
        if not re.match(r"^[A-Z]{4}0[A-Z0-9]{6}$", ifsc_code):
            raise forms.ValidationError(
                "IFSC code must be in the format: AAAA0BBBBBB where AAAA is the bank code and BBBBBB is the branch code."
            )
        return ifsc_code

    def clean_account_number(self):
        account_number = self.cleaned_data.get("account_number", "").strip()
        if len(account_number) < 1:
            raise forms.ValidationError("Account number must not be empty.")
        if not re.match(r"^[0-9\-]+$", account_number):
            raise forms.ValidationError(
                "Account number can only contain digits and hyphens."
            )
        return account_number


class CategoryForm(forms.ModelForm):
    class Meta:
        model = ProductCategory
        fields = (
            "category_name",
            "category_code",
            "icon",
            "standard_image",
            # "banner_image",
        )

    category_name = forms.CharField(
        label="category_name",
        widget=forms.TextInput(
            attrs={"class": "form-control", "id": "category_name_input"}
        ),
        required=True,
    )

    category_code = forms.CharField(
        label="category_code",
        widget=forms.TextInput(
            attrs={"class": "form-control", "id": "category_code_input"}
        ),
    )
    icon = forms.ImageField(
        label="Icon",
        required=False, 
        widget=forms.FileInput(attrs={"id":"upload", "class":"form-control-file"})
    )

    standard_image = forms.ImageField(
        label="Standard Image",
        required=False,
        widget=forms.FileInput(attrs={"id":"upload2", "class":"form-control-file"})
    )

    # banner_image = forms.ImageField(
    #     label="Banner Image",
    #     required=False,
    #     widget=forms.ClearableFileInput(attrs={"id":"upload3", "class":"form-control-file"})
    # )

    def clean_category_name(self):
        category_name = self.cleaned_data.get("category_name").strip()
        if len(category_name) < 1 or len(category_name) > 120:
            raise forms.ValidationError(
                "Category name must be between 1 and 120 characters long."
            )
        if re.search(r"\s{2,}", category_name):
            raise forms.ValidationError("Consecutive spaces not allowed")
        captilized_category_name = category_name.capitalize()
        return captilized_category_name

    def clean_category_code(self):
        category_code = self.cleaned_data.get("category_code").strip()
        if len(category_code) < 2 or len(category_code) > 50:
            raise forms.ValidationError(
                "Category code must be between 2 and 50 characters long."
            )
        if re.search(r"\s{2,}", category_code):
            raise forms.ValidationError("Consecutive spaces not allowed")
        captilized_category_code = category_code.capitalize()
        return captilized_category_code

    def clean_icon(self):
        try:

            icon = self.cleaned_data.get('icon')

            if not icon:
                return icon
                raise ValidationError(f"Icon image needed")

            # Validate file size (example: max 1MB)
            max_size_kb = 800
            if icon.size > max_size_kb * 1024:
                raise ValidationError(f"Image file too large ( > {max_size_kb}KB)")

            # Validate file type (accept only png and jpg)
            img = Image.open(icon)
            image_format = img.format
            content_type_map = {
                'JPEG': 'image/jpeg',
                'PNG': 'image/png',
                'GIF': 'image/gif',
                'BMP': 'image/bmp',
                'TIFF': 'image/tiff',
            }
            content_type = content_type_map.get(image_format, 'unknown')

            if content_type == 'unknown':
                raise ValidationError("Unsupported file type. Only JPG and PNG are allowed.")

            # Validate image dimensions

            max_width, max_height = 100, 100  # Maximum allowed dimensions
            if img.width > max_width or img.height > max_height:
                raise ValidationError(
                    f"Image dimensions too large. Maximum allowed dimensions are {max_width}x{max_height}.")
        except Exception as e:
            if "Upload a valid image" in e:
                raise ValidationError("Upload a valid image.")
            raise ValidationError(e)
        return icon

    def clean_standard_image(self):
        standard_image = self.cleaned_data.get('standard_image')
        if not standard_image:
            return standard_image
            raise ValidationError(f"Standard image needed")

        # Validate file size (example: max 1MB)
        max_size_kb = 800
        if standard_image.size > max_size_kb * 1024:
            raise ValidationError(f"Image file too large ( > {max_size_kb}KB)")

        # Validate file type (accept only png and jpg)

        img = Image.open(standard_image)
        image_format = img.format
        content_type_map = {
            'JPEG': 'image/jpeg',
            'PNG': 'image/png',
            'GIF': 'image/gif',
            'BMP': 'image/bmp',
            'TIFF': 'image/tiff',
        }
        content_type = content_type_map.get(image_format, 'unknown')

        if content_type == 'unknown':
            raise ValidationError("Unsupported file type. Only JPG and PNG are allowed.")

        # Validate image dimensions
        max_width, max_height = 100, 100  # Maximum allowed dimensions
        if img.width > max_width or img.height > max_height:
            raise ValidationError(
                f"Image dimensions too large. Maximum allowed dimensions are {max_width}x{max_height}.")

        return standard_image

    # def clean_banner_image(self):
    #     banner_image = self.cleaned_data.get('banner_image')

    #     # Validate file size (example: max 1MB)
    #     if not banner_image:
    #         return banner_image
    #         raise ValidationError(f"Banner image needed")

    #     max_size_kb = 1024
    #     if banner_image.size > max_size_kb * 1024:
    #         raise ValidationError(f"Image file too large ( > {max_size_kb}KB)")

    #     # Validate file type (accept only png and jpg)

    #     img = Image.open(banner_image)
    #     image_format = img.format
    #     content_type_map = {
    #         'JPEG': 'image/jpeg',
    #         'PNG': 'image/png',
    #         'GIF': 'image/gif',
    #         'BMP': 'image/bmp',
    #         'TIFF': 'image/tiff',
    #     }
    #     content_type = content_type_map.get(image_format, 'unknown')

    #     if content_type == 'unknown':
    #         raise ValidationError("Unsupported file type. Only JPG and PNG are allowed.")

    #     # Validate image dimensions
    #     max_width, max_height = 100, 100  # Maximum allowed dimensions
    #     if img.width > max_width or img.height > max_height:
    #         raise ValidationError(
    #             f"Image dimensions too large. Maximum allowed dimensions are {max_width}x{max_height}.")

    #     return banner_image


class ProductSubCategoryForm(forms.ModelForm):
    class Meta:
        model = ProductSubCategory
        fields = ("sub_category_name", "sub_category_code", "standard_image")

    sub_category_name = forms.CharField(
        label="sub_category_name",
        widget=forms.TextInput(
            attrs={
                "class": "form-control",
                "id": "sub_category_input_name",
                "placeholder": "Sub Category Name",
            }
        ),
        required=True,
    )
    sub_category_code = forms.CharField(
        label="sub_category_code",
        widget=forms.TextInput(
            attrs={
                "class": "form-control",
                "id": "sub_category_input_code",
                "placeholder": "Sub Category Code",
                "arial-label": "sub category code",
                "aria-describedby": "sub_category_submit",
            }
        ),
        required=True,
    )

    standard_image = forms.ImageField(
        label="Standard Image",
        required=False,
        widget=forms.ClearableFileInput(attrs={"id":"upload2", "class":"form-control-file"})
    )

    def clean_sub_category_name(self):
        sub_category_name = self.cleaned_data.get("sub_category_name")
        if len(sub_category_name) < 1 or len(sub_category_name) > 50:
            raise forms.ValidationError(
                "Sub category name must be between 1 and 50 characters long."
            )
        if re.search(r"\s{2,}", sub_category_name):
            raise forms.ValidationError("Consecutive spaces not allowed")
        capitalized_sub_category_name = sub_category_name.title()
        return capitalized_sub_category_name

    def clean_sub_category_code(self):
        sub_category_code = self.cleaned_data.get("sub_category_code", "").strip()

        # Check length constraints
        if len(sub_category_code) < 1 or len(sub_category_code) > 50:
            raise forms.ValidationError(
                "Sub category code must be between 1 and 50 characters long."
            )

        # Prevent consecutive spaces
        if re.search(r"\s{2,}", sub_category_code):
            raise forms.ValidationError("Consecutive spaces not allowed.")

        # Restrict special characters except underscores and hyphens
        if not re.match(r"^[a-zA-Z0-9_-]+$", sub_category_code):
            raise forms.ValidationError("Only letters, numbers, underscores, and hyphens are allowed.")

        # Preserve capitalization: If the original input is all uppercase, keep it that way.
        if sub_category_code.isupper():
            return sub_category_code

        # Otherwise, capitalize only the first letter without modifying the rest
        return sub_category_code[0].upper() + sub_category_code[1:]


    def clean_standard_image(self):
        standard_image = self.cleaned_data.get('standard_image')
        if not standard_image:
            return standard_image
            raise ValidationError(f"Standard image needed")

        # Validate file size (example: max 1MB)
        max_size_kb = 1024
        if standard_image.size > max_size_kb * 1024:
            raise ValidationError(f"Image file too large ( > {max_size_kb}KB)")

        # Validate file type (accept only png and jpg)

        img = Image.open(standard_image)
        image_format = img.format
        content_type_map = {
            'JPEG': 'image/jpeg',
            'PNG': 'image/png',
            'GIF': 'image/gif',
            'BMP': 'image/bmp',
            'TIFF': 'image/tiff',
        }
        content_type = content_type_map.get(image_format, 'unknown')

        if content_type == 'unknown':
            raise ValidationError("Unsupported file type. Only JPG and PNG are allowed.")

        # Validate image dimensions
        max_width, max_height = 1920, 1080  # Maximum allowed dimensions
        if img.width > max_width or img.height > max_height:
            raise ValidationError(
                f"Image dimensions too large. Maximum allowed dimensions are {max_width}x{max_height}.")

        return standard_image


class ProductForm(forms.ModelForm):
    class Meta:
        model = Products
        fields = (
            "product_type",
            "item_name",
            "item_code",
            "i_gst",
            "s_gst",
            "c_gst",
            "cess",
            "item_category",
            "item_sub_category",
            "item_description",
            "veg_or_non_veg_status",
            "images",
            "videos"
        )

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

        # 🔥 FIX: Handle POST data (most important)
        if 'item_category' in self.data:
            try:
                category_id = self.data.get('item_category')
                self.fields['item_sub_category'].queryset = ProductSubCategory.objects.filter(
                    category_id=category_id
                )
            except (ValueError, TypeError):
                self.fields['item_sub_category'].queryset = ProductSubCategory.objects.none()

        # Editing existing product
        elif self.instance and self.instance.pk:
            if self.instance.item_category:
                self.fields['item_sub_category'].queryset = ProductSubCategory.objects.filter(
                    category=self.instance.item_category
                )
            else:
                self.fields['item_sub_category'].queryset = ProductSubCategory.objects.none()

            # Load existing product description data
            try:
                product_description = ProductDescription.objects.get(product=self.instance)
                # Set initial values for description fields
                self.initial['ingredient_info'] = product_description.ingredient_info or ''
                self.initial['nutritional_info'] = product_description.nutritional_info or ''
                self.initial['allergen_description'] = product_description.allergen_description or ''
                self.initial['allergen_info'] = product_description.allergen_info or ''
                self.initial['additional_info'] = product_description.additional_info or ''
            except ProductDescription.DoesNotExist:
                pass

        # New form (initial load)
        else:
            self.fields['item_sub_category'].queryset = ProductSubCategory.objects.none()

    # ------------------ Description Fields (New) ------------------
    
    ingredient_info = forms.CharField(
        label="Ingredients",
        widget=forms.Textarea(attrs={
            "class": "form-control", 
            "id": "ingredient_info",
            "rows": 3,
            "placeholder": "List all ingredients used in this product"
        }),
        required=False,
        help_text="List all ingredients used in this product"
    )

    nutritional_info = forms.CharField(
        label="Nutritional Information",
        widget=forms.Textarea(attrs={
            "class": "form-control", 
            "id": "nutritional_info",
            "rows": 3,
            "placeholder": "Provide nutritional facts (calories, protein, carbs, fats, etc.)"
        }),
        required=False,
        help_text="Provide nutritional facts (calories, protein, carbs, fats, etc.)"
    )

    allergen_description = forms.CharField(
        label="Allergen Description",
        widget=forms.Textarea(attrs={
            "class": "form-control", 
            "id": "allergen_description",
            "rows": 2,
            "placeholder": "Brief description of allergens present"
        }),
        required=False,
        help_text="Brief description of allergens present"
    )

    allergen_info = forms.CharField(
        label="Allergen Information",
        widget=forms.Textarea(attrs={
            "class": "form-control", 
            "id": "allergen_info",
            "rows": 2,
            "placeholder": "Detailed allergen information (contains nuts, gluten, dairy, etc.)"
        }),
        required=False,
        help_text="Detailed allergen information (contains nuts, gluten, dairy, etc.)"
    )

    additional_info = forms.CharField(
        label="Additional Information",
        widget=forms.Textarea(attrs={
            "class": "form-control", 
            "id": "additional_info",
            "rows": 2,
            "placeholder": "Any other relevant product information"
        }),
        required=False,
        help_text="Any other relevant product information"
    )

    # ------------------ Existing Fields ------------------

    item_name = forms.CharField(
        label="Item Name",
        widget=forms.TextInput(attrs={"class": "form-control", "id": "item_name"}),
        required=True,
    )

    item_code = forms.CharField(
        label="Item Code",
        widget=forms.TextInput(attrs={"class": "form-control", "id": "item_code"})
    )

    product_type = forms.CharField(
        initial="Master Product",
        widget=forms.TextInput(
            attrs={
                "class": "form-control",
                "id": "product_type",
                "readonly": "readonly",
            }
        ),
    )

    images = forms.ImageField(
        label="Product Images",
        widget=MultiFileInput(),
        required=False
    )

    videos = forms.FileField(
        label="Product Videos",
        widget=MultiFileInput(),
        required=False
    )

    i_gst = forms.CharField(
        label="IGST",
        required=True,
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "i_gst"}),
    )

    s_gst = forms.CharField(
        label="SGST",
        required=True,
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "s_gst"}),
    )

    c_gst = forms.CharField(
        label="CGST",
        required=True,
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "c_gst"}),
    )

    cess = forms.CharField(
        label="CESS",
        required=True,
        help_text="Enter cess value",
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "cess"}),
    )

    item_category = forms.ModelChoiceField(
        queryset=ProductCategory.objects.all(),
        widget=forms.Select(attrs={"class": "form-control form-select", "id": "id_item_category"}),
        required=True,
        error_messages={"required": "Please select an item category."},
    )

    item_sub_category = forms.ModelChoiceField(
        queryset=ProductSubCategory.objects.none(),  # dynamically set
        widget=forms.Select(attrs={"class": "form-control form-select", "id": "id_item_sub_category"}),
        required=True,
        error_messages={"required": "Please select an item sub-category."},
    )

    item_description = forms.CharField(
        widget=forms.Textarea(
            attrs={
                "class": "form-control",
                "rows": 5,
                "placeholder": "Enter description",
                "id": "item_description"
            }
        )
    )

    veg_or_non_veg_status = forms.ChoiceField(
        choices=[("Veg", "Veg"), ("Non Veg", "Non Veg")],
        widget=forms.Select(
            attrs={"class": "form-control form-select", "id": "veg_or_non_veg_status"}
        ),
    )

    # ------------------ Validations ------------------

    def clean_item_name(self):
        item_name = self.cleaned_data.get("item_name").strip()
        if len(item_name) < 1 or len(item_name) > 120:
            raise forms.ValidationError(
                "Item name must be between 1 and 120 characters long."
            )
        if re.search(r"\s{2,}", item_name):
            raise forms.ValidationError("Consecutive spaces not allowed.")
        return item_name

    def clean_item_code(self):
        item_code = self.cleaned_data.get("item_code").strip()
        if len(item_code) < 1 or len(item_code) > 120:
            raise forms.ValidationError(
                "Item code must be between 1 and 120 characters long."
            )
        if re.search(r"\s{2,}", item_code):
            raise forms.ValidationError("Consecutive spaces not allowed.")
        return item_code

    def clean_decimal(self, field_name, label, positive=False):
        value = self.cleaned_data.get(field_name)
        try:
            if value is not None:
                value = round(Decimal(value), 2)

                if positive and value <= 0:
                    raise forms.ValidationError(f"{label} must be a positive number.")
        except (InvalidOperation, ValueError):
            raise forms.ValidationError(f"Enter a valid decimal number for {label}.")
        return value

    def clean_i_gst(self):
        return self.clean_decimal("i_gst", "IGST", positive=True)

    def clean_s_gst(self):
        return self.clean_decimal("s_gst", "SGST", positive=True)

    def clean_c_gst(self):
        return self.clean_decimal("c_gst", "CGST", positive=True)

    def clean_cess(self):
        return self.clean_decimal("cess", "CESS")

    # ------------------ Override save method to handle ProductDescription ------------------
    
    def save(self, commit=True):
        product = super().save(commit=commit)
        
        if commit:
            # Handle Product Description
            product_description, created = ProductDescription.objects.get_or_create(product=product)
            product_description.ingredient_info = self.cleaned_data.get('ingredient_info', '')
            product_description.nutritional_info = self.cleaned_data.get('nutritional_info', '')
            product_description.allergen_description = self.cleaned_data.get('allergen_description', '')
            product_description.allergen_info = self.cleaned_data.get('allergen_info', '')
            product_description.additional_info = self.cleaned_data.get('additional_info', '')
            product_description.save()
        
        return product

class SKUForm(forms.ModelForm):
    class Meta:
        model = SKU
        fields = (
            "sku_name",
            "sku_code",
            "sku_quantity",
            "sku_unit",
            "sku_mrp",
            "same_day_delivery",
            "customization_available",
            "sku_expiry_duration",
            "sku_bulk_qty_limit",
            "sku_status"
        )

    sku_name = forms.CharField(
        label="SKU Name",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )

    sku_code = forms.CharField(
        label="SKU Code",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )

    sku_quantity = forms.IntegerField(
        label="Quantity",
        widget=forms.NumberInput(attrs={"class": "form-control"}),
        required=True,
        error_messages={
            "required": "Enter a valid field",
            "invalid": "Enter a valid field",
        },
    )

    sku_unit = forms.CharField(
        label="Unit",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )

    sku_mrp = forms.FloatField(
        label="MRP",
        widget=forms.NumberInput(attrs={"class": "form-control"}),
        required=True,
        error_messages={
            "required": "Enter a valid field",
            "invalid": "Enter a valid field",
        },
    )

    same_day_delivery = forms.BooleanField(
        label="same_day_delivery",
        required=False,  # Set to False if you want the field to be optional
        widget=CheckboxInput(attrs={"name": "same_day_delivery", "id": "same_day_delivery_id", "class": "form-check-input",
                                    "style": "margin-left: -25px;"})

    )

    customization_available = forms.BooleanField(
        label="customization_available",
        required=False,  # Set to False if you want the field to be optional
        widget=CheckboxInput(attrs={"name": "customization_available", "id": "customization_available_id", "class": "form-check-input",
                                    "style": "margin-left: -25px;"})

    )

    sku_expiry_duration = forms.IntegerField(
        label="Expiry Duration (days)",
        widget=forms.NumberInput(attrs={"class": "form-control"}),
        required=True,
        error_messages={
            "required": "Enter a valid field",
            "invalid": "Enter a valid field",
        },
    )

    sku_bulk_qty_limit = forms.IntegerField(
        label="Bulk Quantity Limit",
        widget=forms.NumberInput(attrs={"class": "form-control"}),
        required=True,
        error_messages={
            "required": "Enter a valid field",
            "invalid": "Enter a valid field",
        },

    )

    sku_status = forms.ChoiceField(
        choices=[('Visible', 'Visible'), ('Disabled', 'Disabled'), ('Out of Stock', 'Out of Stock')],
        widget=forms.Select(attrs={"class": "form-control form-select"}),
        required=True,
    )

    # Custom validation methods for specific fields
    def clean_sku_quantity(self):
        return self.clean_positive_integer("sku_quantity", label="SKU Quantity")

    def clean_sku_mrp(self):
        return self.clean_decimal("sku_mrp", label="SKU MRP", positive=True)

    def clean_sku_expiry_duration(self):
        return self.clean_positive_integer("sku_expiry_duration", label="SKU Expiry Duration")

    def clean_sku_bulk_qty_limit(self):
        return self.clean_positive_integer("sku_bulk_qty_limit", label="SKU Bulk Quantity Limit")

    def clean_decimal(self, field_name, label, positive=False):
        value = self.cleaned_data.get(field_name)
        try:
            if value is not None:
                # Ensure the value is formatted to two decimal places
                value = round(Decimal(value), 2)

                # Check for positivity if required
                if positive and value <= 0:
                    raise forms.ValidationError(f"{label} must be a positive number.")
        except (InvalidOperation, ValueError):
            raise forms.ValidationError(f"Enter a valid field for {label}.")
        return value

    def clean_positive_integer(self, field_name, label):
        value = self.cleaned_data.get(field_name)
        if value is None or int(value) <= 0:
            raise forms.ValidationError(f"{label} must be a positive number.")
        return value





class ShopAdminSelectorModelChoiceField(forms.ModelChoiceField):
    def label_from_instance(self, obj):
        self.widget_attrs(
            {"style": "width:200px;"},
        )
        return "%s" % obj.module_name


class StoreUserForm(forms.ModelForm):
    class Meta:
        model = Users
        fields = ("phone", "email")

    phone_regex = RegexValidator(
        regex=r"^\+?1?\d{9,15}$",
        message="Phone number must be entered in the format: '9999999999'. Up to 10 digits allowed.",
    )
    phone = phone = forms.CharField(
        max_length=10,
        validators=[phone_regex],
        widget=forms.TextInput(attrs={"class": "form-control"}),
    )
    email = forms.EmailField(widget=forms.EmailInput(attrs={"class": "form-control"}))

    def clean_phone(self):
        phone = self.cleaned_data.get("phone")
        if Users.objects.filter(phone=phone).exists():
            raise ValidationError("Phone number already exists.")
        return phone


class StoreUserFormStatusEdit(forms.ModelForm):
    class Meta:
        model = Users
        fields = ("status",)
        status = forms.ChoiceField(
            choices=[("active", "active"), ("inactive", "inactive")],
            widget=forms.Select(attrs={"class": "form-control form-select", "id": "status-select"}),
        )


class UserModalForm(forms.ModelForm):
    class Meta:
        model = Users
        fields = (
            "first_name",
            "last_name",
            "email",
            "user_type",
            "phone_number",
            "status",
        )

    first_name = forms.CharField(
        label="first_name",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )

    last_name = forms.CharField(
        label="last_name", widget=forms.TextInput(attrs={"class": "form-control"})
    )

    email = forms.EmailField(
        label="email", widget=forms.TextInput(attrs={"class": "form-control"})
    )

    user_type = forms.CharField(
        widget=forms.TextInput(
            attrs={
                "class": "form-control",
                "id": "user_type-select",
                "readonly": "readonly",
                "value": "Shop Admin",
            }
        )
    )

    phone_number = forms.CharField(
        label="phone_number", widget=forms.TextInput(attrs={"class": "form-control"})
    )
    status = forms.ChoiceField(
        choices=[("active", "active"), ("inactive", "inactive")],
        widget=forms.Select(attrs={"class": "form-control form-select", "id": "status-select"}),
    )

    def clean_first_name(self):
        first_name = self.cleaned_data.get('first_name')
        if len(first_name) < 3:
            raise forms.ValidationError("Username must be at least 3 characters long.")
        if re.search(r'[!@#$%^&*(),.?":{}|<>]', first_name):
            raise forms.ValidationError('Special characters are not allowed in the username.')
        if first_name.isnumeric():
            raise forms.ValidationError('Username could not be numbers.')
        if re.search(r'\s{2,}', first_name):
            raise forms.ValidationError('Consecutive spaces not allowed')
        capitalize_first_name = first_name.capitalize()

        return capitalize_first_name

    def clean_last_name(self):
        last_name = self.cleaned_data.get('last_name')

        if re.search(r'[!@#$%^&*(),.?":{}|<>]', last_name):
            raise forms.ValidationError('Special characters are not allowed in the username.')
        if last_name.isnumeric():
            raise forms.ValidationError('Username could not be numbers.')
        if re.search(r'\s{2,}', last_name):
            raise forms.ValidationError('Consecutive spaces not allowed')
        capitalize_last_name = last_name.capitalize()

        return capitalize_last_name

    def clean_phone_number(self):
        phone_number = self.cleaned_data.get('phone_number')
        if not re.match(r'^\+?1?\d{9,15}$', phone_number):
            raise ValidationError("Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
        return phone_number


class TagForm(forms.ModelForm):
    class Meta:
        model = Tags
        fields = (
            "tag_name",
            "icon",
            "products"
        )

    tag_name = forms.CharField(
        label="tag_name",
        widget=forms.TextInput(attrs={"name" : "tag_name", "id": "tag_name_id","class": "form-control", "type":"text", "placeholder": "Enter tag"}),
        required=True,
    )

    icon = forms.ImageField(
        label="Icon",
        required=False,
        widget=forms.ClearableFileInput(attrs={"id":"upload", "class":"form-control-file"})
    )

    products = forms.ModelMultipleChoiceField(
        queryset=Products.objects.all(),
        widget=forms.SelectMultiple(attrs={"class": "form-control", "size": "10", "id": "product_id"}),
        error_messages={"required": "Please select at least one product."},
    )


    def clean_tag_name(self):
        tag_name = self.cleaned_data.get('tag_name')
        if len(tag_name) < 3:
            raise forms.ValidationError("Tag name must be at least 3 characters long.")
        if re.search(r'[!@#$%^&*(),.?":{}|<>]', tag_name):
            raise forms.ValidationError('Special characters are not allowed in the tag name.')
        if tag_name.isnumeric():
            raise forms.ValidationError('Tag name could not be numbers.')
        if re.search(r'\s{2,}', tag_name):
            raise forms.ValidationError('Consecutive spaces not allowed')
        capitalize_tag_name = tag_name.title()

        return capitalize_tag_name


    def clean_icon(self):
        try:

            icon = self.cleaned_data.get('icon')

            if not icon:
                return icon
                raise ValidationError(f"Icon image needed")


            # Validate file size (example: max 1MB)
            max_size_kb = 1024
            if icon.size > max_size_kb * 1024:
                raise ValidationError(f"Image file too large ( > {max_size_kb}KB)")

            # Validate file type (accept only png and jpg)
            img = Image.open(icon)
            image_format = img.format
            content_type_map = {
                'JPEG': 'image/jpeg',
                'PNG': 'image/png',
                'GIF': 'image/gif',
                'BMP': 'image/bmp',
                'TIFF': 'image/tiff',
            }
            content_type = content_type_map.get(image_format, 'unknown')

            if content_type == 'unknown':
                raise ValidationError("Unsupported file type. Only JPG and PNG are allowed.")

            # Validate image dimensions

            max_width, max_height = 1920, 1080  # Maximum allowed dimensions
            if img.width > max_width or img.height > max_height:
                raise ValidationError(
                    f"Image dimensions too large. Maximum allowed dimensions are {max_width}x{max_height}.")
        except Exception as e:
            if "Upload a valid image" in e:
                raise ValidationError("Upload a valid image.")
            raise ValidationError(e)
        return icon






class DynamicFilterForm(forms.ModelForm):
    class Meta:
        model = DynamicFiltering
        fields = (
            "filter_name",
            "products"
        )

    filter_name = forms.CharField(
        label="filter_name",
        widget=forms.TextInput(attrs={"name" : "filter_name", "id": "filter_name_id","class": "form-control", "type":"text", "placeholder": "Enter dynamic filter"}),
        required=True,
    )

    products = forms.ModelMultipleChoiceField(
        queryset=Products.objects.all(),
        widget=forms.SelectMultiple(attrs={"class": "form-control", "size": "10", "id": "product_id"}),
        error_messages={"required": "Please select at least one product."},
    )


    def clean_filter_name(self):
        filter_name = self.cleaned_data.get('filter_name')
        if len(filter_name) < 3:
            raise forms.ValidationError("Dynamic filter name must be at least 3 characters long.")
        if re.search(r'[!@#$%^&*(),.?":{}|<>]', filter_name):
            raise forms.ValidationError('Special characters are not allowed in the tag name.')
        if filter_name.isnumeric():
            raise forms.ValidationError('Tag name could not be numbers.')
        if re.search(r'\s{2,}', filter_name):
            raise forms.ValidationError('Consecutive spaces not allowed')
        capitalize_filter_name = filter_name.capitalize()

        return capitalize_filter_name



class SpecialListForm(forms.ModelForm):
    class Meta:
        model = SpecialList
        fields = (
            "special_name",
            "icon",
            "standard_image",
            "banner_image",
            "products"
        )

    special_name = forms.CharField(
        label="special_name",
        widget=forms.TextInput(attrs={"name" : "special_name", "id": "special_name_id","class": "form-control", "type":"text", "placeholder": "Enter special name"}),
        required=True,
    )

    icon = forms.ImageField(
        label="Icon",
        required=False,
        widget=forms.ClearableFileInput(attrs={"id":"upload", "class":"form-control-file"})
    )

    standard_image = forms.ImageField(
        label="Standard Image",
        required=False,
        widget=forms.ClearableFileInput(attrs={"id":"upload2", "class":"form-control-file"})
    )

    banner_image = forms.ImageField(
        label="Banner Image",
        required=False,
        widget=forms.ClearableFileInput(attrs={"id":"upload3", "class":"form-control-file"})
    )

    products = forms.ModelMultipleChoiceField(
        queryset=Products.objects.all(),
        widget=forms.SelectMultiple(attrs={"class": "form-control", "size": "10", "id": "product_id"}),
        error_messages={"required": "Please select at least one product."},
    )


    def clean_special_name(self):
        special_name = self.cleaned_data.get('special_name')
        if len(special_name) < 3:
            raise forms.ValidationError("Special name must be at least 3 characters long.")
        if re.search(r'[!@#$%^&*(),.?":{}|<>]', special_name):
            raise forms.ValidationError('Special characters are not allowed in the special name.')
        if special_name.isnumeric():
            raise forms.ValidationError('Special name could not be numbers.')
        if re.search(r'\s{2,}', special_name):
            raise forms.ValidationError('Consecutive spaces not allowed')
        capitalize_special_name = special_name.title()

        return capitalize_special_name

    def clean_icon(self):
        try:

            icon = self.cleaned_data.get('icon')

            if not icon:
                return icon
                raise ValidationError(f"Icon image needed")


            # Validate file size (example: max 1MB)
            max_size_kb = 1024
            if icon.size > max_size_kb * 1024:
                raise ValidationError(f"Image file too large ( > {max_size_kb}KB)")

            # Validate file type (accept only png and jpg)
            img = Image.open(icon)
            image_format = img.format
            content_type_map = {
                'JPEG': 'image/jpeg',
                'PNG': 'image/png',
                'GIF': 'image/gif',
                'BMP': 'image/bmp',
                'TIFF': 'image/tiff',
            }
            content_type = content_type_map.get(image_format, 'unknown')

            if content_type == 'unknown':
                raise ValidationError("Unsupported file type. Only JPG and PNG are allowed.")

            # Validate image dimensions

            max_width, max_height = 1920, 1080  # Maximum allowed dimensions
            if img.width > max_width or img.height > max_height:
                raise ValidationError(
                    f"Image dimensions too large. Maximum allowed dimensions are {max_width}x{max_height}.")
        except Exception as e:
            if "Upload a valid image" in e:
                raise ValidationError("Upload a valid image.")
            raise ValidationError(e)
        return icon

    def clean_standard_image(self):
        standard_image = self.cleaned_data.get('standard_image')
        if not standard_image:
            return standard_image
            raise ValidationError(f"Standard image needed")

        # Validate file size (example: max 1MB)
        max_size_kb = 1024
        if standard_image.size > max_size_kb * 1024:
            raise ValidationError(f"Image file too large ( > {max_size_kb}KB)")

        # Validate file type (accept only png and jpg)

        img = Image.open(standard_image)
        image_format = img.format
        content_type_map = {
            'JPEG': 'image/jpeg',
            'PNG': 'image/png',
            'GIF': 'image/gif',
            'BMP': 'image/bmp',
            'TIFF': 'image/tiff',
        }
        content_type = content_type_map.get(image_format, 'unknown')

        if content_type == 'unknown':
            raise ValidationError("Unsupported file type. Only JPG and PNG are allowed.")

        # Validate image dimensions
        max_width, max_height = 1920, 1080  # Maximum allowed dimensions
        if img.width > max_width or img.height > max_height:
            raise ValidationError(
                f"Image dimensions too large. Maximum allowed dimensions are {max_width}x{max_height}.")

        return standard_image

    def clean_banner_image(self):
        banner_image = self.cleaned_data.get('banner_image')

        # Validate file size (example: max 1MB)
        if not banner_image:
            return banner_image
            raise ValidationError(f"Banner image needed")

        max_size_kb = 1024
        if banner_image.size > max_size_kb * 1024:
            raise ValidationError(f"Image file too large ( > {max_size_kb}KB)")

        # Validate file type (accept only png and jpg)

        img = Image.open(banner_image)
        image_format = img.format
        content_type_map = {
            'JPEG': 'image/jpeg',
            'PNG': 'image/png',
            'GIF': 'image/gif',
            'BMP': 'image/bmp',
            'TIFF': 'image/tiff',
        }
        content_type = content_type_map.get(image_format, 'unknown')

        if content_type == 'unknown':
            raise ValidationError("Unsupported file type. Only JPG and PNG are allowed.")

        # Validate image dimensions
        max_width, max_height = 1920, 1080  # Maximum allowed dimensions
        if img.width > max_width or img.height > max_height:
            raise ValidationError(
                f"Image dimensions too large. Maximum allowed dimensions are {max_width}x{max_height}.")

        return banner_image



class DeliveryBoyForm(forms.ModelForm):
    class Meta:
        model = DeliveryBoys
        fields = (
            "team_member_name",
            "phone_number",
            "email"
        )

    team_member_name = forms.CharField(
        label="team_member_name",
        widget=forms.TextInput(attrs={"name" : "team_member_name", "id": "team_member_name_id","class": "form-control", "type":"text"}),
        required=True,
    )

    phone_number = forms.CharField(
        label="phone_number",
        widget=forms.TextInput(attrs={"name" : "phone_number", "id": "phone_number_id","class": "form-control", "type":"text", "value":"+91", "onfocus":"addCountryCode()"}),
        required=True,
    )
    email = forms.EmailField(
        required=True,
        label="Email Address",
        max_length=254,
        widget=forms.EmailInput(attrs={'placeholder': 'Enter your email', "class": "form-control"})
    )

    def clean_phone_number(self):
        phone = self.cleaned_data["phone_number"].strip()

        if not phone.startswith("+91"):  # Ensure +91 is always there
            raise forms.ValidationError("Phone number must start with +91.")

        # Extract only digits after +91
        phone_number = phone.replace("+91", "").strip()

        if not phone_number.isdigit() or len(phone_number) != 10:
            raise forms.ValidationError("Enter a valid 10-digit phone number.")

        return "+91" + phone_number  # Store in database with +91





class CourierDetailsForm(forms.ModelForm):
    class Meta:
        model = OrderDelivery
        fields = (
            "courier_service_name",
            "package_number",
            "expected_date_of_delivery",
            "tracking_link",
        )

    courier_service_name = forms.CharField(
        label="courier_service_name",
        widget=forms.TextInput(attrs={"name" : "courier_service_name", "id": "courier_service_name_id","class": "form-control", "type":"text"}),
        required=True,
    )

    package_number = forms.CharField(
        label="package_number",
        widget=forms.TextInput(attrs={"name" : "package_number", "id": "package_number_id","class": "form-control", "type":"text"}),
        required=True,
    )

    expected_date_of_delivery = forms.DateField(
        widget=forms.DateInput(format='%Y-%m-%d', attrs={'type': 'date'}),
        input_formats=['%d/%m/%Y', '%Y-%m-%d'],  # Accept both DD/MM/YYYY and YYYY-MM-DD
        required= True
    )

    tracking_link = forms.CharField(
        label="tracking_link",
        widget=forms.TextInput(attrs={"name" : "tracking_link", "id": "tracking_link_id","class": "form-control", "type":"text"}),
        required=True,
    )


class CouponForm(forms.ModelForm):
    class Meta:
        model = Coupons
        fields = (
            "CouponName",
            "CouponCode",
            "CouponDescription",
            "Icon",
            "CouponOn",
            "ApplicableCategory",
            "ApplicableSubCategory",
            "ApplicableProduct",
            "ApplicableSku",
            "TotalBillAmount",
            "DiscountAmount",
            "DiscountPercentage",
            "MaxDiscountAmountForPercentage",
            "CouponType",
            "MaxNumberofUsers",
            "Validity_start_date",
            "validity_end_date",
            "TermsAndConditions",
            #"NotificationSchedule",
        )

    CouponName = forms.CharField(
        label="Coupon Name",
        widget=forms.TextInput(attrs={
            "class": "form-control",
            "placeholder": "Please fill out this field",
            "required": "required",  # Add this to enable browser validation
        }),
        required=True,  # This ensures server-side validation
    )


    CouponCode = forms.CharField(
        label="CouponCode",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )

    CouponDescription = forms.CharField(
        label="CouponDescription",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )

    Icon = forms.ImageField(
        label="Icon",
        required=False,
        widget=forms.ClearableFileInput(attrs={"id":"upload", "class":"form-control-file"})
    )


    CouponOn = forms.ChoiceField(
        choices=[('Category', 'Category'), ('SubCategory', 'SubCategory'), ('Product', 'Product'),('Sku', 'Sku')],
        widget=forms.Select(
            attrs={
                "class": "form-control form-select",
                "id": "coupon_select",
            }
        ),
        required=True,
    )

    ApplicableCategory = forms.ModelMultipleChoiceField(
        queryset=ProductCategory.objects.filter().all(),
        widget=forms.SelectMultiple(attrs={"class": "form-control", "size": "10"}),
        required=False
    )
    ApplicableSubCategory = forms.ModelMultipleChoiceField(
        queryset=ProductSubCategory.objects.all(),
        widget=forms.SelectMultiple(attrs={"class": "form-control", "size": "10"}),
        required=False
    )
    ApplicableProduct = forms.ModelMultipleChoiceField(
        queryset=Products.objects.all(),
        widget=forms.SelectMultiple(attrs={"class": "form-control", "size": "10"}),
        required=False
    )
    ApplicableSku = forms.ModelMultipleChoiceField(
        queryset=SKU.objects.all(),
        widget=forms.SelectMultiple(attrs={"class": "form-control", "size": "10"}),
        required=False
    )

    TotalBillAmount = forms.CharField(
        label="GSTIN",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    DiscountAmount = forms.DecimalField(
        required=False, decimal_places=2, max_digits=10, label='Discount Amount',
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "discount_amount_field"})
    )
    DiscountPercentage = forms.DecimalField(
        required=False, decimal_places=2, max_digits=5, label='Discount Percentage',
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "discount_percentage_field"})
    )
    MaxDiscountAmountForPercentage = forms.FloatField(
        label="Maximum Discount Amount for Percentage",
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "max_discount_field"}),
        required=False,
        help_text="Maximum discount amount when coupon type is percentage."
    )
    CouponType = forms.ChoiceField(
        choices = [('amount','amount'), ('percentage', 'percentage')],
        widget=forms.Select(
            attrs={
                "class": "form-control form-select",
                "id": "coupon_type",  
            }
        ),
        required=True,
    )
    MaxNumberofUsers = forms.IntegerField(
        label="MaxNumberofUsers",
        widget=forms.TextInput(attrs={"class": "form-control", "max_length": "6"}),
        required=True,
    )
    Validity_start_date = forms.DateField(
        widget=forms.DateInput(format='%Y-%m-%d', attrs={'type': 'date', 'class': 'form-control'}),
        input_formats=['%d/%m/%Y', '%Y-%m-%d']  # Accept both DD/MM/YYYY and YYYY-MM-DD
    )

    validity_end_date = forms.DateField(
        widget=forms.DateInput(format='%Y-%m-%d', attrs={'type': 'date', 'class': 'form-control'}),
        input_formats=['%d/%m/%Y', '%Y-%m-%d']
    )
    TermsAndConditions = forms.CharField(
        widget=forms.Textarea(attrs={'class': 'form-control', 'placeholder': 'Enter your comments...'}),
        label='TermsAndConditions',
        required=True
    )
    #NotificationSchedule = forms.DateTimeField(widget=forms.TextInput(attrs={'class': 'form-control datetimepicker', "max_length" :"6"}))

    def clean_CouponName(self):
        data = self.cleaned_data.get('CouponName')
        if not data:
            raise forms.ValidationError("This field is required.")
        return data






    def clean_Icon(self):
        try:

            Icon = self.cleaned_data.get('Icon')

            if not Icon:
                return Icon
                raise ValidationError(f"Icon image needed")

            # Validate file size (example: max 1MB)
            max_size_kb = 1024
            if Icon.size > max_size_kb * 1024:
                raise ValidationError(f"Image file too large ( > {max_size_kb}KB)")

            # Validate file type (accept only png and jpg)
            img = Image.open(Icon)
            image_format = img.format
            content_type_map = {
                'JPEG': 'image/jpeg',
                'PNG': 'image/png',
                'GIF': 'image/gif',
                'BMP': 'image/bmp',
                'TIFF': 'image/tiff',
            }
            content_type = content_type_map.get(image_format, 'unknown')

            if content_type == 'unknown':
                raise ValidationError("Unsupported file type. Only JPG and PNG are allowed.")

            # Validate image dimensions

            max_width, max_height = 1920, 1080  # Maximum allowed dimensions
            if img.width > max_width or img.height > max_height:
                raise ValidationError(
                    f"Image dimensions too large. Maximum allowed dimensions are {max_width}x{max_height}.")
        except Exception as e:
            if "Upload a valid image" in e:
                raise ValidationError("Upload a valid image.")
            raise ValidationError(e)
        return Icon

    def clean_validity_end_date(self):
        start_date = self.cleaned_data.get("Validity_start_date")
        end_date = self.cleaned_data.get("validity_end_date")

        if start_date and end_date and end_date < start_date:
            raise ValidationError("End date cannot be earlier than the start date.")

        return end_date

    def clean(self):

        coupon_on = self.cleaned_data.get('CouponOn', "")
        minimum_bill_amount = self.cleaned_data.get('TotalBillAmount', "")
        applicable_category = self.cleaned_data.get('ApplicableCategory', None)
        applicable_subcategory = self.cleaned_data.get('ApplicableSubCategory', None)
        applicable_product = self.cleaned_data.get('ApplicableProduct', None)
        applicable_sku = self.cleaned_data.get('ApplicableSku', None)

        if coupon_on == "Category":

            if not applicable_category:
                raise ValidationError({"ApplicableCategory": "Field required!"})

            products = Products.objects.filter(item_category__in=applicable_category)
            for i in products:
                sku = SKU.objects.filter(product=i.id).first()
                if float(minimum_bill_amount) >= float(sku.sku_mrp):
                    raise ValidationError({"TotalBillAmount": "Coupon not valid for some products on category!"})

        if coupon_on == "SubCategory":
            if not applicable_subcategory:
                raise ValidationError({"ApplicableSubCategory": "Field required!"})

            products = Products.objects.filter(item_sub_category__in=applicable_subcategory)

            for i in products:
                sku = SKU.objects.filter(product=i.id).first()
                if float(minimum_bill_amount) >= float(sku.sku_mrp):
                    raise ValidationError({"TotalBillAmount": "Coupon not valid for some products on sub category!"})

        if coupon_on == "Product":
            if not applicable_product:
                raise ValidationError({"ApplicableProduct": "Field required!"})
            products = Products.objects.filter(id__in = applicable_product)
            for i in products:
                sku = SKU.objects.filter(product = i.id).first()
                if float(minimum_bill_amount) >= float(sku.sku_mrp):
                    raise ValidationError({"TotalBillAmount": "Coupon not valid for some product!"})

        if coupon_on == "Sku":
            if not applicable_sku:
                raise ValidationError({"ApplicableSku": "Field required!"})

            skus = SKU.objects.filter(id__in = applicable_sku)
            for sku in skus:
                if float(minimum_bill_amount) >= float(sku.sku_mrp):
                    raise ValidationError({"TotalBillAmount": "Coupon not valid for SKU!"})





class DeliverySlotForm(forms.ModelForm):
    class Meta:
        model = DeliverySlot
        fields = (
            # "shop",
            "start_time",
            "end_time",
            "is_available",
            "status"
        )


    # shop = forms.ModelChoiceField(
    #         label="shop",
    #         queryset=Shop.objects.all(),
    #         widget=forms.Select(attrs={"class": "form-control form-select", "name" : "shop_name", "id": "shop_Id"}),
    #         required=True,
    #         error_messages={"required": "Please select a shop."},
    #     )

    start_time = forms.TimeField(
        widget=forms.TimeInput(
            attrs={ "type" : "time","name" : "start_time_name", "id": "start_time_id","class": "form-control"}),
        label='start_time',
        required=True,
    )
    end_time = forms.TimeField(
        widget=forms.TimeInput(attrs={"type": "time","name": "end_time_name", "id": "end_time_id", "class": "form-control"}),
        label='end_time',
        required=True,
    )
    is_available =  forms.BooleanField(
        label="is_available",
        required=False,  # Set to False if you want the field to be optional
        widget = CheckboxInput(attrs={"name" :"is_available", "id": "is_available_checkbox", "class": "form-check-input",  "style" : "margin-left: -25px;"})

    )
    status = forms.ChoiceField(
        choices=[('active', 'active'), ('inactive', 'inactive')],
        widget=forms.Select(
            attrs={
                "class": "form-control form-select",
                "id": "status_select",
            }
        ),
        required=True,
    )
    #
    # def __init__(self, *args, **kwargs):
    #     self.request = kwargs.pop('request', None)  # Pop `request` from kwargs
    #     super().__init__(*args, **kwargs)
    #
    # def save(self, commit=True):
    #     instance = super().save(commit=False)
    #     # Modify the instance before saving
    #     # shop_id_verify = Shop.objects.prefetch_related('unit_admin_user').filter(
    #     #     unit_admin_user__uuid=self.request.user.uuid)
    #     # shop_id = shop_id_verify[0]
    #     # instance.shop  =  shop_id
    #     if commit:
    #         instance.save()
    #     return instance




class DiscountForm(forms.ModelForm):
    class Meta:
        model = Discount
        fields = (
            "DiscountName",
            "DiscountCode",
            "DiscountDescription",
            "DiscountOn",
            "ApplicableCategory",
            "ApplicableSubCategory",
            "ApplicableProduct",
            "ApplicableSku",
            "DiscountPercentage",
            'StandardImage',
            'BannerImage',
        )

    DiscountName = forms.CharField(
        label="DiscountName",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    DiscountCode = forms.CharField(
        label="DiscountCode",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    DiscountDescription = forms.CharField(
        label="DiscountDescription",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    DiscountOn = forms.ChoiceField(
        choices=[('Category', 'Category'), ('SubCategory', 'SubCategory'), ('Product', 'Product'), ('Sku', 'Sku')],
        widget=forms.Select(
            attrs={
                "class": "form-control form-select",
                "id": "discount_select",
            }
        ),
        required=True,
    )

    ApplicableCategory = forms.ModelMultipleChoiceField(
        queryset=ProductCategory.objects.filter().all(),
        widget=forms.SelectMultiple(attrs={"class": "form-control", "size": "10"}),
        required=False
    )
    ApplicableSubCategory = forms.ModelMultipleChoiceField(
        queryset=ProductSubCategory.objects.all(),
        widget=forms.SelectMultiple(attrs={"class": "form-control", "size": "10"}),
        required=False
    )
    ApplicableProduct = forms.ModelMultipleChoiceField(
        queryset=Products.objects.all(),
        widget=forms.SelectMultiple(attrs={"class": "form-control", "size": "10"}),
        required=False
    )
    ApplicableSku = forms.ModelMultipleChoiceField(
        queryset=SKU.objects.all(),
        widget=forms.SelectMultiple(attrs={"class": "form-control", "size": "10"}),
        required=False
    )

    DiscountPercentage = forms.IntegerField(  # Changed to IntegerField
        label="Discount Percentage",
        widget=forms.NumberInput(attrs={"class": "form-control"}),
        required=True,
        min_value=1,  # Ensures it's a positive number
        error_messages={'min_value': 'Discount percentage must be a positive number.'},
    )
    StandardImage = forms.ImageField(
        label="Standard Image",
        required=False,
        widget=forms.ClearableFileInput(attrs={"id": "upload2", "name": "StandardImage", "class": "form-control-file"})
    )
    BannerImage = forms.ImageField(
        label="Banner Image",
        required=False,
        widget=forms.ClearableFileInput(attrs={"id": "upload3", "name": "BannerImage", "class": "form-control-file"})
    )

    def clean_DiscountPercentage(self):
        discount_percentage = self.cleaned_data.get('DiscountPercentage')
        if discount_percentage <= 0: # type: ignore
            raise forms.ValidationError("Discount percentage must be a positive whole number.")
        return discount_percentage

    def clean_ApplicableCategory(self):
        data = self.cleaned_data.get('ApplicableCategory')
        # Custom validation logic here if needed
        return data

    def clean_ApplicableSubCategory(self):
        data = self.cleaned_data.get('ApplicableSubCategory')
        # Custom validation logic here if needed
        return data


    
    def clean_StandardImage(self):
        standard_image = self.cleaned_data.get('StandardImage')
        if not standard_image:
            raise ValidationError(f"Standard image needed")

        # Validate file size (example: max 1MB)
        max_size_kb = 1024
        if standard_image.size > max_size_kb * 1024:
            raise ValidationError(f"Image file too large ( > {max_size_kb}KB)")

        # Validate file type (accept only png and jpg)

        img = Image.open(standard_image)
        image_format = img.format
        content_type_map = {
            'JPEG': 'image/jpeg',
            'PNG': 'image/png',
            'GIF': 'image/gif',
            'BMP': 'image/bmp',
            'TIFF': 'image/tiff',
        }
        content_type = content_type_map.get(image_format, 'unknown')

        if content_type == 'unknown':
            raise ValidationError("Unsupported file type. Only JPG and PNG are allowed.")

        # Validate image dimensions
        max_width, max_height = 1080, 490  # Maximum allowed dimensions
        if img.width > max_width or img.height > max_height:
            raise ValidationError(
                f"Image dimensions too large. Maximum allowed dimensions are {max_width}x{max_height}.")

        return standard_image
    
    def clean_BannerImage(self):
        banner_image = self.cleaned_data.get('BannerImage')

        # Validate file size (example: max 1MB)
        if not banner_image:
            raise ValidationError(f"Banner image needed")

        max_size_kb = 1024
        if banner_image.size > max_size_kb * 1024:
            raise ValidationError(f"Image file too large ( > {max_size_kb}KB)")

        # Validate file type (accept only png and jpg)

        img = Image.open(banner_image)
        image_format = img.format
        content_type_map = {
            'JPEG': 'image/jpeg',
            'PNG': 'image/png',
            'GIF': 'image/gif',
            'BMP': 'image/bmp',
            'TIFF': 'image/tiff',
        }
        content_type = content_type_map.get(image_format, 'unknown')

        if content_type == 'unknown':
            raise ValidationError("Unsupported file type. Only JPG and PNG are allowed.")

        # Validate image dimensions
        max_width, max_height = 360, 175  # Maximum allowed dimensions
        if img.width > max_width or img.height > max_height:
            raise ValidationError(
                f"Image dimensions too large. Maximum allowed dimensions are {max_width}x{max_height}.")

        return banner_image

    def clean_DiscountCode(self):
        discount_code = self.cleaned_data.get('DiscountCode')
        if Discount.objects.filter(DiscountCode=discount_code).exclude(DiscountCode=self.instance.DiscountCode).exists():
            raise forms.ValidationError("A discount with this code already exists. Please use a unique code.")
        return discount_code

    def clean(self):

        discount_on = self.cleaned_data.get('DiscountOn', "")
        applicable_category = self.cleaned_data.get('ApplicableCategory', None)
        applicable_subcategory = self.cleaned_data.get('ApplicableSubCategory', None)
        applicable_product = self.cleaned_data.get('ApplicableProduct', None)
        applicable_sku = self.cleaned_data.get('ApplicableSku', None)

        if discount_on == "Category":

            if not applicable_category:
                raise ValidationError({"ApplicableCategory": "Field required!"})


        if discount_on == "SubCategory":
            if not applicable_subcategory:
                raise ValidationError({"ApplicableSubCategory": "Field required!"})

            products = Products.objects.filter(item_sub_category__in=applicable_subcategory)


        if discount_on == "Product":
            if not applicable_product:
                raise ValidationError({"ApplicableProduct": "Field required!"})


        if discount_on == "Sku":
            if not applicable_sku:
                raise ValidationError({"ApplicableSku": "Field required!"})










class AdForm(forms.ModelForm):
    placement_choices = [('Top', 'Top'), ('Bottom', 'Bottom'), ('Banner', 'Banner')]


    class Meta:
        model = Ads
        fields = (
            'AdTitle',
            'AdDescription',
            'AdPlacement',
            'AdType',
            'StandardImage',
            'BannerImage',
            'Discount',
            'Coupon',
            'Product'

        )

    AdTitle = forms.CharField(
        label="Ad Title",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    AdDescription = forms.CharField(
        label="Ad Description",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    AdPlacement = forms.MultipleChoiceField(
        choices=placement_choices,
        widget=forms.CheckboxSelectMultiple(attrs={ 'id': 'multi-select'}),
        required=False
    )


    AdType = forms.ChoiceField(
        choices=[('Discount', 'Discount'), ('Coupon', 'Coupon'), ('Product', 'Product')],
        widget=forms.Select(
            attrs={
                "class": "form-control form-select",
                "id": "Ad_communication_select",
            }
        ),
        required=True,
    )
    Discount = forms.ModelChoiceField(
        queryset=Discount.objects.all(),
        label="Discount",
        widget=forms.Select(attrs={"class": "form-control discount", "id": "discount_id"}),
        required=False,
    )

    Coupon = forms.ModelChoiceField(
        queryset=Coupons.objects.all(),
        label="Coupon",
        widget=forms.Select(attrs={"class": "form-control coupon", "id": "coupon_id"}),
        required=False,
    )
    Product = forms.ModelChoiceField(
        queryset=Products.objects.all(),
        label="Product",
        widget=forms.Select(attrs={"class": "form-control product", "id": "product_id"}),
        required=False,
    )
    StandardImage = forms.ImageField(
        label="Standard Image",
        required=False,
        widget=forms.ClearableFileInput(attrs={"id": "upload2", "name": "StandardImage", "class": "form-control-file"})
    )
    BannerImage = forms.ImageField(
        label="Banner Image",
        required=False,
        widget=forms.ClearableFileInput(attrs={"id": "upload3", "name": "BannerImage", "class": "form-control-file"})
    )

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)  # Pop `request` from kwargs
        instance = kwargs.get('instance')
        if instance:
            initial = kwargs.setdefault('initial', {})
            initial['AdPlacement'] = instance.get_placement_display()
        super().__init__(*args, **kwargs)


    def clean_StandardImage(self):
        standard_image = self.cleaned_data.get('StandardImage')
        if not standard_image:
            raise ValidationError(f"Standard image needed")

        # Validate file size (example: max 1MB)
        max_size_kb = 1024
        if standard_image.size > max_size_kb * 1024:
            raise ValidationError(f"Image file too large ( > {max_size_kb}KB)")

        # Validate file type (accept only png and jpg)

        img = Image.open(standard_image)
        image_format = img.format
        content_type_map = {
            'JPEG': 'image/jpeg',
            'PNG': 'image/png',
            'GIF': 'image/gif',
            'BMP': 'image/bmp',
            'TIFF': 'image/tiff',
        }
        content_type = content_type_map.get(image_format, 'unknown')

        if content_type == 'unknown':
            raise ValidationError("Unsupported file type. Only JPG and PNG are allowed.")

        # Validate image dimensions
        max_width, max_height = 1080, 590  # Maximum allowed dimensions
        if img.width > max_width or img.height > max_height:
            raise ValidationError(
                f"Image dimensions too large. Maximum allowed dimensions are {max_width}x{max_height}.")

        return standard_image

    def clean_AdPlacement(self):
        ad_placement = self.cleaned_data.get('AdPlacement')
        if not ad_placement:
            raise ValidationError(f"Please select atleast 1 placement!")
        return ad_placement

    def clean_BannerImage(self):
        banner_image = self.cleaned_data.get('BannerImage')

        # Validate file size (example: max 1MB)
        if not banner_image:
            raise ValidationError(f"Banner image needed")

        max_size_kb = 1024
        if banner_image.size > max_size_kb * 1024:
            raise ValidationError(f"Image file too large ( > {max_size_kb}KB)")

        # Validate file type (accept only png and jpg)

        img = Image.open(banner_image)
        image_format = img.format
        content_type_map = {
            'JPEG': 'image/jpeg',
            'PNG': 'image/png',
            'GIF': 'image/gif',
            'BMP': 'image/bmp',
            'TIFF': 'image/tiff',
        }
        content_type = content_type_map.get(image_format, 'unknown')

        if content_type == 'unknown':
            raise ValidationError("Unsupported file type. Only JPG and PNG are allowed.")

        # Validate image dimensions
        max_width, max_height = 360, 175   # Maximum allowed dimensions
        if img.width > max_width or img.height > max_height:
            raise ValidationError(
                f"Image dimensions too large. Maximum allowed dimensions are {max_width}x{max_height}.")

        return banner_image




    def clean_Discount(self):
        ad_type = self.cleaned_data.get('AdType')
        if  ad_type == 'Discount':
            if self.cleaned_data.get('Discount') == '':
                raise ValidationError("Discount Cannot be empty!")
    def clean_Coupon(self):
        ad_type = self.cleaned_data.get('AdType')
        if  ad_type == 'Coupon':
            if self.cleaned_data.get('Coupon') == '':

                raise ValidationError("Coupon Cannot be  empty!")


    def clean_Product(self):
        ad_type = self.cleaned_data.get('AdType')
        if  ad_type == 'Product':
            if self.cleaned_data.get('Product') == '':
                raise ValidationError("Product Cannot be empty!")

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

        # Temporarily skip setting Many-to-Many field to avoid validation error
        instance.AdPlacement = ','.join(self.cleaned_data['AdPlacement'])
        if commit:
            instance.save()

        return instance










class CustomProductForm(forms.ModelForm):
    class Meta:
        model = CustomProduct
        fields = (
            "item_name",
            "item_code",
            "item_description",
            "veg_or_non_veg_status",
            "min_size",
            "max_size",
            "size_unit",
            "images",
            "videos",
            "availability",
        )

    item_name = forms.CharField(
        label="Item Name",
        widget=forms.TextInput(attrs={"class": "form-control", "id": "item_name"}),
        required=True,
    )
    item_code = forms.CharField(
        label="Item Code",
        widget=forms.TextInput(attrs={"class": "form-control", "id": "item_code"}),
        required=True,
    )

    item_description = forms.CharField(
        label="Item Description",
        widget=forms.Textarea(attrs={"class": "form-control", "id": "item_description", "rows": 5}),
        required=True,
    )

    veg_or_non_veg_status = forms.ChoiceField(
        choices=[("Veg", "Veg"), ("Non Veg", "Non Veg")],
        widget=forms.Select(attrs={"class": "form-control", "id": "veg_or_non_veg_status"}),
    )

    min_size = forms.FloatField(
        label="Minimum Size",
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "min_size"}),
        required=True,
    )

    max_size = forms.FloatField(
        label="Maximum Size",
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "max_size"}),
        required=True,
    )

    size_unit = forms.ChoiceField(
        choices=[("g", "g"), ("kg", "kg"), ("ml", "ml"), ("ltr", "ltr")],
        widget=forms.Select(attrs={"class": "form-control", "id": "size_unit"}),
        required=True,
    )

    images = forms.ImageField(
        label="Product Images",
        widget=MultiFileInput(),
        required=False,  # Keep as optional or change based on your requirement
    )

    videos = forms.FileField(
        label="Product Videos",
        widget=MultiFileInput(),
        required=False,  # Changed from required=True to required=False
    )

    # Add the availability field to the form
    availability = forms.ChoiceField(
        label="Availability",
        choices=CustomProduct.AVAILABILITY_CHOICES,
        widget=forms.Select(attrs={"class": "form-control", "id": "availability"}),
        required=True,
    )

    def clean_item_name(self):
        item_name = self.cleaned_data.get("item_name").strip()
        if len(item_name) < 1 or len(item_name) > 120:
            raise forms.ValidationError(
                "Item name must be between 1 and 120 characters long."
            )
        return item_name

    def clean_item_description(self):
        item_description = self.cleaned_data.get("item_description").strip()
        if len(item_description) < 1 or len(item_description) > 1300:
            raise forms.ValidationError(
                "Description must be between 1 and 1300 characters long."
            )
        return item_description

    def clean_min_size(self):
        min_size = self.cleaned_data.get("min_size")
        if min_size <= 0:
            raise forms.ValidationError("Minimum size must be greater than 0.")
        return min_size

    def clean_max_size(self):
        max_size = self.cleaned_data.get("max_size")
        if max_size <= 0:
            raise forms.ValidationError("Maximum size must be greater than 0.")
        return max_size

    def clean_images(self):
        images = self.files.getlist("images")

        # Make images optional
        if not images:
            return None

        max_size_kb = 800
        max_width, max_height = 150, 150
        allowed_formats = ["JPEG", "PNG", "JPG"]

        error_messages = []

        for image in images:
            print(
                f"Image: {image.name}, "
                f"Size: {image.size} bytes, "
                f"{image.size / 1024:.2f} KB"
            )

            # ✅ Size validation
            if image.size > max_size_kb * 1024:
                error_messages.append(
                    f"Image file size should not exceed {max_size_kb}KB."
                )
                continue

            try:
                img = Image.open(image)
                img.verify()  # Validate image integrity

                # 🔴 CRITICAL FIX
                image.seek(0)

                img = Image.open(image)

                image_format = img.format.upper() if img.format else None

                # ✅ Format validation
                if image_format not in allowed_formats:
                    error_messages.append("Only JPG and PNG image formats are allowed.")
                    continue

                # ✅ Dimension validation
                if img.width > max_width or img.height > max_height:
                    error_messages.append(
                        f"Image dimensions should not exceed {max_width}x{max_height} pixels."
                    )
                    continue

            except Exception as e:
                print(f"Image validation error: {e}")
                error_messages.append(
                    "Invalid image file. Please check the format and try again."
                )
                continue

        if error_messages:
            raise ValidationError(list(set(error_messages))[0])

        return images

    def clean_videos(self):
        videos = self.files.getlist("videos")  # Supports multiple videos
        
        # Make videos optional - no validation if no videos
        if not videos:
            return None  # Allow no videos
            
        # If videos are uploaded, validate them
        max_size_mb = 10  # Max file size 10MB
        allowed_video_formats = ['mp4', 'avi', 'mov', 'mkv']  # Add allowed formats
        
        for video in videos:
            # Validate file size
            if video.size > max_size_mb * 1024 * 1024:
                raise ValidationError(f"Video {video.name} is too large (>{max_size_mb}MB).")
            
            # Validate file extension
            file_extension = video.name.split('.')[-1].lower()
            if file_extension not in allowed_video_formats:
                raise ValidationError(f"Unsupported video format: {file_extension}. Allowed formats: {', '.join(allowed_video_formats)}")
        
        return videos










class ProductionUnitForm(forms.ModelForm):
    class Meta:
        model = ProductionUnit
        fields = (
            "pu_name",
            "pu_location",
            "pu_code",
            "street",
            "city",
            "district",
            "state_or_province",
            "pin_code",
            "latitude",
            "longitude",
            "contact_no",
            "email",
            "gst",
            "status",
        )

    pu_name = forms.CharField(
        label="unit_name",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    pu_location = forms.CharField(
        label="unit_location",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )

    pu_code = forms.CharField(
        label="unit_code",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )


    street = forms.CharField(
        label="Street",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    city = forms.CharField(
        label="city",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    district = forms.CharField(
        label="District",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    state_or_province = forms.CharField(
        label="state",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )
    pin_code = forms.IntegerField(
        label="Pin Code",
        widget=forms.TextInput(attrs={"class": "form-control", "max_length": "6"}),
        required=True,
    )
    latitude = forms.CharField(
        label="latitude",
        widget=forms.TextInput(attrs={"class": "form-control", "readonly": "readonly"}),
        required=True,
    )
    longitude = forms.CharField(
        label="longitude",
        widget=forms.TextInput(attrs={"class": "form-control", "readonly": "readonly"}),
        required=True,
    )
    contact_no = forms.CharField(
        label="Contact Number",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=False,
    )
    email = forms.EmailField(
        label="Email ID",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=False,
    )

    gst = forms.CharField(
        label="gst",
        widget=forms.TextInput(attrs={"class": "form-control"}),
        required=True,
    )


    status = forms.ChoiceField(
        choices=[("open", "open"), ("close", "close")],
        widget=forms.Select(
            attrs={"class": "form-control form-select", "id": "status-select"}
        ),
        required=True,
    )




    def clean_pu_name(self):
        pu_name = self.cleaned_data.get("pu_name")
        if len(pu_name) < 3 or len(pu_name) > 120:
            raise forms.ValidationError(
                "Unit name must be between 3 and 120 characters long."
            )
        if not re.match(r"^[a-zA-Z0-9\s@.,-]+$", pu_name):
            raise forms.ValidationError(
                "Unit name may only contain alphabets, numerics, spaces, and some special characters like '@', '.', ',', and '-'."
            )
        if re.search(r"\s{2,}", pu_name):
            raise forms.ValidationError("Consecutive spaces not allowed")
        capitalize_first_name = pu_name.capitalize()

        return pu_name




    def clean_contact_no(self):
        phone_number = self.cleaned_data.get("contact_no")
        if not re.match(r"^\+?1?\d{9,15}$", phone_number):
            raise ValidationError(
                "Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed."
            )
        return phone_number
    

class FAQForm(forms.ModelForm):
    class Meta:
        model = FAQ
        fields = ('category', 'question', 'answer')

    category = forms.ChoiceField(
        label="Category",
        choices=FAQ.CATEGORY_CHOICES,
        widget=forms.Select(attrs={
            "name": "category",
            "id": "category_id",
            "class": "form-control",
        }),
        required=True,
    )

    question = forms.CharField(
        label="Question",
        widget=forms.TextInput(attrs={
            "name": "question",
            "id": "question_id",
            "class": "form-control",
            "type": "text",
        }),
        required=True,
    )

    answer = forms.CharField(
        label="Answer",
        widget=forms.Textarea(attrs={
            "name": "answer",
            "id": "answer_id",
            "class": "form-control",
            "rows": 5,
            "cols": 40,
        }),
        required=True,
    )


class AboutUsForm(forms.ModelForm):
    content = forms.CharField(widget=CKEditorWidget())
    class Meta:
        model = AboutUs
        fields = ['content', 'image'] 

class PrivacyPolicyForm(forms.ModelForm):
    content = forms.CharField(widget=CKEditorWidget())
    class Meta:
        model = PrivacyPolicy
        fields = ['content']  

class TermsAndConditionsForm(forms.ModelForm):
    content = forms.CharField(widget=CKEditorWidget())
    class Meta:
        model = TermsAndConditions
        fields = ['content'] 

class ContactUsForm(forms.ModelForm):
    class Meta:
        model = ContactUs
        fields = ['phone_number', 'email']

class AppUrlForm(forms.ModelForm):
    class Meta:
        model = AppUrl
        fields = ['playstore_link', 'appstore_link']

class RefundPolicyForm(forms.ModelForm):
    content = forms.CharField(widget=CKEditorWidget())
    class Meta:
        model = ReturnPolicy
        fields = ['content']


class CustomOrderForm(forms.ModelForm):
    class Meta:
        model = Orders
        fields = ('order_ID','sub_total', 'taxes_and_charges', 'delivery_charges', 'discount','grand_total', )


    order_ID = forms.CharField(label="order_ID", widget=forms.TextInput(attrs={
        "class": "form-control",
        "id": "order_Id",
        "readonly": "readonly"

    }))

    sub_total = forms.FloatField(
        label="sub_total",
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "sub_total"}),
        required=True,
    )

    taxes_and_charges = forms.FloatField(
        label="taxes_and_charges",
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "taxes_and_charges"}),
        required=True,
    )
    delivery_charges = forms.FloatField(
        label="delivery_charges",
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "delivery_charges"}),
        required=True,
    )

    grand_total = forms.FloatField(
        label="grand_total",
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "grand_total", "readonly" :True}),
        required=True,
    )
    

    discount = forms.FloatField(
        label="discount",
        widget=forms.NumberInput(attrs={"class": "form-control", "id": "discount"}),
        required=True,
    )

    def clean_grand_total(self):
        grand_total = self.cleaned_data.get("grand_total")
        if int(grand_total) < 0:
            raise forms.ValidationError(
                "Grand Total should be greater than 0"
            )

        return grand_total

class MessageForm(forms.ModelForm):
    class Meta:
        model = Message
        fields = ("message_type", "subject", "message")
    
    message = forms.CharField(
        label="Message",
        widget=forms.Textarea(attrs={
            "class": "form-control",
            "rows": "5",
            "placeholder": "Enter your message here...",
            "id": "message_input"
        }),
        required=True
    )
    
    message_type = forms.ChoiceField(
        label="Message Type",
        choices=Message.MESSAGE_TYPE_CHOICES,   # USE MODEL CHOICES
        widget=forms.Select(attrs={
            "class": "form-control form-select",
            "id": "message_type_select"
        }),
        required=True
    )
    
    subject = forms.CharField(
        label="Subject",
        widget=forms.TextInput(attrs={
            "class": "form-control",
            "placeholder": "Enter email subject...",
            "id": "subject_input"
        }),
        required=False  # Will be made required only for email via JavaScript
    )
    
    def clean(self):
        cleaned_data = super().clean()
        message_type = cleaned_data.get('message_type')
        subject = cleaned_data.get('subject')
        
        # For email type, subject field is required
        if message_type == 'email' and not subject:
            self.add_error('subject', 'Subject is required for email messages.')
        
        return cleaned_data


class YouMayAlsoLikeForm(forms.ModelForm):
    class Meta:
        model = YouMayAlsoLike
        fields = (
            "product",
            "liked_products"
        )
    product = forms.ModelChoiceField(queryset = Products.objects.all(), widget=forms.Select(attrs={"name": "product", "id": "product_select", "class": "form-control select2", "placeholder": "Select Product"}), error_messages={"required": "Please select a product."},required=True)

    liked_products = forms.ModelMultipleChoiceField(
        queryset=Products.objects.all(),
        widget=forms.SelectMultiple(attrs={"class": "form-control", "size": "10", "id": "product_id"}),
        error_messages={"required": "Please select at least one product."},
    )


class DeliverySettingsForm(forms.ModelForm):
    class Meta:
        model = DeliverySettings
        fields = [
            'base_fee', 'base_km', 'per_km_fee',
            'free_delivery_min_order_value', 'free_delivery_max_distance'
        ]
        widgets = {
            'base_fee': forms.NumberInput(attrs={'class': 'form-control'}),
            'base_km': forms.NumberInput(attrs={'class': 'form-control'}),
            'per_km_fee': forms.NumberInput(attrs={'class': 'form-control'}),
            'free_delivery_min_order_value': forms.NumberInput(attrs={'class': 'form-control'}),
            'free_delivery_max_distance': forms.NumberInput(attrs={'class': 'form-control'}),
        }

class DeliveryDiscountForm(forms.ModelForm):
    class Meta:
        model = DeliveryDiscount
        fields = ['min_order_value', 'discount_percent']
        widgets = {
            'min_order_value': forms.NumberInput(attrs={'class': 'form-control'}),
            'discount_percent': forms.NumberInput(attrs={'class': 'form-control'}),
        }
        labels = {
            'min_order_value': 'Starts From Order Value (₹)',
            'discount_percent': 'Discount %',
        }

class CustomCouponSettingsForm(forms.ModelForm):
    class Meta:
        model = CustomCouponSettings
        fields = ['coupon_name', 'coupon_description', 'lower_limit_price', 'higher_limit_price', 'discount_amount']
        widgets = {
            'coupon_name': forms.TextInput(attrs={"class": "form-control"}),
            'coupon_description': forms.Textarea( attrs={
                "class": "form-control",
                "rows": 5,
                "placeholder": "Enter description",
                "id": "coupon_description"
            }),
            'discount_amount': forms.NumberInput(attrs={'class': 'form-control'}),
            'lower_limit_price': forms.NumberInput(attrs={'class': 'form-control'}),
            'higher_limit_price': forms.NumberInput(attrs={'class': 'form-control'})
        }
        labels = {
            'coupon_name': 'Coupon Name',
            'coupon_description': 'Coupon Description',
            'lower_limit_price':"Lower Order Price",
            'higher_limit_price': "Upper Order Price"
        }



class ShopSlobIdForm(forms.ModelForm):
    class Meta:
        model = ShopSlobId
        fields = ['shop', 'slob_id']

    def clean(self):
        cleaned_data = super().clean()
        shop = cleaned_data.get("shop")
        slob_id = cleaned_data.get("slob_id")

        # 1️⃣ Check if shop already has slob id
        if shop and ShopSlobId.objects.filter(shop=shop).exists():
            raise forms.ValidationError(
                "This shop already has a Slob ID assigned."
            )

        # 2️⃣ Check if slob id already used by another shop
        if slob_id and ShopSlobId.objects.filter(slob_id=slob_id).exists():
            raise forms.ValidationError(
                "This Slob ID is already assigned to another shop."
            )

        return cleaned_data