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):
    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_items(self):
        items = self.cleaned_data.get("unit_admin_user")
        if not items:
            raise forms.ValidationError("There should be atleast one shop admin user")
        return items

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

    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")
        capitalize_first_name = shop_name.capitalize()

        return shop_name

    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 whole number")
        return delivery_radius


    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

    def clean_unit_admin_user(self):
        unit_admin_user = self.cleaned_data.get("unit_admin_user")
        shop = Shop.objects.filter(unit_admin_user__in = unit_admin_user).exclude(uuid = self.instance.uuid)
        if shop:
            users = []
            for i in unit_admin_user:
                unit_admin_check = shop.filter(unit_admin_user__in = [i])
                if unit_admin_check:
                    users.append(f"{i.first_name} {i.last_name}")
            name_list = ",".join(users)
            raise ValidationError(f"Shop Admin {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.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"})
    )

    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"
        )

    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.all(),
        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"}
        ),
    )


    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:
                # 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 decimal number 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
    def clean_i_gst(self):
        return self.clean_decimal("i_gst", positive=True,label="IGST")

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

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

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


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, 720  # 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 = 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

    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 = 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_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 = 1080, 720   # 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",  # Add availability to the list of 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"}),
        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,
    )

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


    # Add the availability field to the form
    availability = forms.ChoiceField(
        label="Availability",
        choices=CustomProduct.AVAILABILITY_CHOICES,  # This uses the choices defined in the model
        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")  # Supports multiple images

        if not images:
            raise ValidationError("At least one image is required.")

        max_size_kb = 800  # Max file size 1MB
        max_width, max_height = 150, 150  # Max dimensions

        allowed_formats = ["JPEG", "PNG"]

        for image in images:
            # Validate file size
            if image.size > max_size_kb * 1024:
                raise ValidationError(f"Image {image.name} is too large (>{max_size_kb}KB).")

            try:
                img = Image.open(image)
                image_format = img.format

                # Validate file type
                if image_format not in allowed_formats:
                    raise ValidationError(f"Unsupported file type: {image_format}. Only JPG and PNG are allowed.")

                # Validate image dimensions
                if img.width > max_width or img.height > max_height:
                    raise ValidationError(
                        f"Image {image.name} is too large. Max allowed dimensions: {max_width}x{max_height} pixels."
                    )

            except Exception as e:
                raise ValidationError(f"Invalid image file {image.name}: {e}")











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 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", "message", "ads")

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

    message_type=forms.ChoiceField(label="message_type",choices=[("email", "Email"), ("sms", "SMS"),("whatsapp","WhatsApp")],
        widget=forms.Select(attrs={"class": "form-control form-select"}),required=True,)
    
    ads = forms.ModelChoiceField(queryset=Ads.objects.all(),to_field_name="uuid",label="Message Subject",
                                 widget=forms.Select(attrs={"class": "form-control form-select"}))


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"
        }



