from appservices.common.util import *
from flask_wtf import FlaskForm
from wtforms import StringField,RadioField,TextAreaField, PasswordField, SubmitField, SelectMultipleField,SelectField,FileField,IntegerField,BooleanField,FieldList,DateTimeLocalField,FormField,FloatField,HiddenField,TimeField
from wtforms.validators import DataRequired, ValidationError, Length,NumberRange, Optional,Regexp,InputRequired,AnyOf,URL, EqualTo
from bson import ObjectId, errors as bson_errors
from flask_wtf.file import FileAllowed, FileRequired





# Default Lengths
MIN_LENGTH_1 = 1        # Minimum length: 1 character
MIN_LENGTH_2 = 2        # Minimum length: 2 characters
MIN_LENGTH_3 = 3        # Minimum length: 3 characters
MIN_LENGTH_4 = 4        # Minimum length: 3 characters
MIN_LENGTH_10 = 10      # Minimum length: 1 character
MIN_LENGTH_11 = 11  
    # Minimum length: 1 character
MAX_LENGTH_3 = 3 
MAX_LENGTH_10 = 10       # Maximum length: 3 characters
MAX_LENGTH_15 = 15      # Maximum length: 15 characters
MAX_LENGTH_32 = 32      # Maximum length: 15 characters
MAX_LENGTH_75 = 75      # Maximum length: 75 characters
MAX_LENGTH_150= 150  

##############
TIME_PATTERN = r"^(?:[01]\d|2[0-3]):[0-5]\d$"
# Regex Patterns
PASSWORD_REGEX = r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_\-+[\]{}:;\"',./\\<>?|`~])[A-Za-z\d!@#$%^&*()_\-+[\]{}:;\"',./\\<>?|`~]{8,30}$"
EMAIL_REGEX = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
ALPHABETS_WITH_SPACE_REGEX = r"^[a-zA-Z\s@#$()+_\-/]*$" ## only alphabetic characters (letters) and spaces.
ALPHANUMERIC_REGEX = r"^[a-zA-Z0-9\s@#$()+_\-/.]*$" ##  alphanumeric characters and special characters(letters and digits).
# ALPHANUMERIC_REGEX_NUMBER_3_75 = r"^[a-zA-Z0-9\s@#$()+_\-/.]{3,75}*$" ##  alphanumeric characters and special characters(letters and digits).
ONLY_NUMERIC = r"^\d+(\.\d+)?$" ## string contains only numeric characters.
IFSC_REGEX = r"^[A-Za-z]{4}\d{1}[A-Za-z0-9]{6}$" # 4 letters, 1 digit, and 6 alphanumeric characters.
DESCRIPTION = r'^[\s\S]*$'   ##allows alphabets, numbers, spaces, special characters, and newlines
PHONE_NUMBER_REGEX = r"^[0-9]{1,10}$" # Regex for 10-digit phone number
NUMBER_REGEX = r"^[0-9]{1,5}$" # Regex for 5-digit phone number
TRANSACTION_LIMIT = r"^[0-9]+([.][0-9]*)?|[.][0-9]$" 
DOCUMENTS_EXTENSIONS =  {'pdf', 'jpg', 'jpeg'}
IMAGES_EXTENSIONS = {'jpg', 'jpeg', 'png'} 
CSV_EXTENSIONS = {'csv'} 
ALPHANUMERIC_WITHOUT_SPECIAL_CHARACTERS  = r"^[a-zA-Z0-9\s]+$" ##alphanumeric characters (letters, digits) and spaces.####### use for bankcode etc
ALPHANUMERIC_WITHOUT_SPACE  = r"^[a-zA-Z0-9]+$" ##alphanumeric characters (letters, digits) and spaces.####### use for bankcode etc
NUMERIC_WITH_DOTS_REGEX = r"^\d+(\.\d+)*$" ## only numeric characters and allows multiple dots.
COUNTRY_CODE_REGEX = r"^\+?[0-9]{1,4}$"
LATITUDE_REGEX = r"^-?(90(\.0{1,6})?|[0-8]?[0-9](\.[0-9]{1,6})?)$"
LONGITUDE_REGEX = r"^-?(180(\.0{1,6})?|1[0-7][0-9](\.[0-9]{1,6})?|[0-9]{1,2}(\.[0-9]{1,6})?)$"
COUNTRY_CODE = r'^\+([1-9][0-9]{0,2})$'
COUNTRY_REGEX = r'^\+?[1-9]\d{1,14}$'
DECIMALPOINT_REGEX = r'^\d{1,10}(\.\d+)?$'
ALPHANUMERIC_REGEX_WITH_DOT= r'^[a-zA-Z0-9.\s]+$'
ACCOUNT_NUMBER_REGEX = r"^\d{9,20}$"
ALPHANUMERIC_REGEX_WITH_UNDERSCORE_HYPHEN_DOT=r"^[a-zA-Z0-9_\-\.]+$"

CONTACT_EMAIL_REGEX = r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)"
CONTACT_PHONE_NUMBER_REGEX = r"^\d{10}$"
URL_REGEX = r"^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([/\w \.-]*)*\/?$"
STATE_CODE_REGEX = r"\b(0[1-9]|1[0-9]|2[0-9]|3[0-8])\b"
# Messages
INVALID_FORMAT_MESSAGE = "Invalid Format"
INVALID_LENGTH_MESSAGE = "Invalid Length"
INVALID_Image_MESSAGE = "Invalid image format"


#### for single status remark  use this
class UpdateStatusRemarkForm(FlaskForm):
    remark = StringField('', validators=[DataRequired(),Length(min=1, max=100,message="Remark must be between 1 and 100 characters."),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/.")])



def MaxDigitsBeforeDecimal(max_digits):
        def _validate(form, field):
            if field.data is not None:
                try:
                    integer_part = str(field.data).split('.')[0]
                    if len(integer_part) > max_digits:
                        raise ValidationError(f'Must be {max_digits} digits or fewer before the decimal point.')
                except (ValueError, AttributeError):
                    raise ValidationError('Invalid number format.')
        return _validate
  

class MerchantWisePayinPayout(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
    class Meta:
        csrf = False 

class BankForm(FlaskForm):
    bankName = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message="Please enter a Bank name between 3 and 75 characters"),Regexp(ALPHANUMERIC_REGEX, message="Bank Name can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    bankCode = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_15,message="Please enter a Bank code between 1 and 15 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPECIAL_CHARACTERS, message="Bank Code can only contain letters, numbers")])
    ifscCode = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_11, max=MIN_LENGTH_11,message="Please enter an IFSC of 11 characters"),Regexp(IFSC_REGEX, message="IFSC code must be 11 characters long and follow the format: 4 letters, followed by 0, then 6 digits")])
    priority = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MIN_LENGTH_10,message="Please enter a Priority between 3 and 75 characters"),Regexp(NUMBER_REGEX, message="Priority Must be only of Numeric format")])
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None

    def validate_bankName(self, field):
        existing = MasterIFSCBank.objects(bankName=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Bank Name already exists.')

    def validate_bankCode(self, field):
        existing = MasterIFSCBank.objects(bankCode=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Bank Code already exists.')

    def validate_ifscCode(self, field):
        existing = MasterIFSCBank.objects(ifscCode=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('IFSC Code already exists.')
        

class BankFormSearch(FlaskForm):
    search_element = StringField('',validators=[Optional(),
            Length(min=MIN_LENGTH_3,max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE),
            Regexp(ALPHANUMERIC_REGEX, message="Search field must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    class Meta:
        csrf = False          


class BankFormRemark(FlaskForm):
    remark = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE),
            Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])


class BankCodeForm(FlaskForm):
    bankCode = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_15,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX_WITH_UNDERSCORE_HYPHEN_DOT, message=INVALID_FORMAT_MESSAGE)])
    bankId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    transactionApiIdsList = SelectMultipleField('', choices=[],validate_choice=False, validators=[DataRequired()])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_bankId(self, field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid bankId format.")
        banks_queryset =  MasterIFSCBank.objects(id=field.data,status__in=[0,1]).first()
        if not banks_queryset:
            raise ValidationError("Selected bank is not valid.")
          
    def validate_transactionApiIdsList(self, field):
        valid_count = TransactionAPI.objects(id__in=field.data,status__in=[0,1]).count()
        if valid_count != len(field.data):
            raise ValidationError("One or more selected APIs are invalid.")
        

    def validate(self, extra_validators=None):
        if not super().validate(extra_validators=extra_validators):
            return False

        from bson import ObjectId

        bankId = self.bankId.data
        bankCode = self.bankCode.data
        transactionApiIdsList = self.transactionApiIdsList.data
        errors_found = False

        # Check for existing transactionApiIdsList combinations
        bcode_queryset = BankCodes.objects(bankId=bankId, status=1)
        for bcode in bcode_queryset:
            if self.current_id and str(bcode.id) == self.current_id:
                continue  # Skip self during update
            existing_ids = {str(api.id) for api in bcode.transactionApiIdsList}
            if any(api_id in existing_ids for api_id in transactionApiIdsList):
                self.transactionApiIdsList.errors.append("This combination of APIs already exists for the selected bank.")
                errors_found = True
                break

        # Check if the same bankCode already exists with any of the given APIs
        code_queryset = BankCodes.objects(transactionApiIdsList__in=transactionApiIdsList, status=1)
        for bcode in code_queryset:
            if self.current_id and str(bcode.id) == self.current_id:
                continue # Skip self during update
            if bcode.bankCode == bankCode:
                self.bankCode.errors.append("The bank code already exists for the selected APIs.")
                errors_found = True
                break

        return not errors_found

class BankCodesSearchForm(FlaskForm):
    bankSearchId = SelectField('', choices=[], validate_choice=False)  # optional
    transactionApiId = SelectField('', choices=[], validate_choice=False)  # optional
    def validate_bankSearchId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid bank ID format. Please select a valid bank.")
        
            banks_queryset = MasterIFSCBank.objects(id=field.data,status__in=[0,1]).first()
            if not banks_queryset:
                raise ValidationError("Selected bank is not valid.")
        
    def validate_transactionApiId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid transaction API ID format.")
        
            api_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1]).first()
            if not api_queryset:
                raise ValidationError("Please select a valid payment gateway.")

    class Meta:
        csrf = False          

class PaymentModeForm(FlaskForm):
    paymentMode = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    walletType = StringField('', validators=[DataRequired()])
    hasGroup  = StringField('', validators=[DataRequired()])
    # priority = StringField('', validators=[DataRequired(),NumberRange(min=0, max=9999, message="Priority must be between 0 and 9999."),Regexp(ONLY_NUMERIC, message=INVALID_FORMAT_MESSAGE)])
    priority = IntegerField('', validators=[
        DataRequired(),
        NumberRange(min=0, max=9999, message="Priority must be between 0 and 9999.")
    ])
    groupType  = StringField('', validators=[DataRequired()])
    image = FileField('', validators=[Optional(),FileAllowed(['jpg', 'jpeg', 'png'], INVALID_Image_MESSAGE)])

   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_paymentMode(self, field):
        existing = PaymentMode.objects(paymentMode=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Payment Mode already exists.')      
        
    
class PaymentModeFormSearch(FlaskForm):
    paymentMode = StringField('', validators=[
        Optional(),
        Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="Payment Mode must be between 3 and 75 characters long."),
        Regexp(ALPHANUMERIC_REGEX, message="Payment Mode can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")
    ])
    # walletType = StringField('Wallet Type', validators=[Optional()])
    

    walletType = SelectField('Wallet Type',
    choices=[
        ("", "Select Wallet"),
        ("Payout", "Payout"),
        ("Payin", "Payin")
    ],validators=[
        Optional()
    ],
    coerce=str)

    class Meta:
        csrf = False


class SubPaymentModeForm(FlaskForm):
    subPaymentModeType = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    paymentModeId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    # priority = FloatField('', validators=[DataRequired(),Length(min=MIN_LENGTH_1, max=MIN_LENGTH_4,message=INVALID_LENGTH_MESSAGE),Regexp(ONLY_NUMERIC, message=INVALID_FORMAT_MESSAGE)])
    priority = IntegerField('', validators=[
        DataRequired(),
        NumberRange(min=0, max=9999, message="Priority must be between 0 and 9999.")
    ])
    minAmount = FloatField('Min Amount', validators=[
        DataRequired(message="Min Amount is required."),
        NumberRange(min=0, max=9999999999, message="Min Amount must be between 0 and 9999999999.")
    ])

    maxAmount = FloatField('Max Amount', validators=[
        DataRequired(message="Max Amount is required."),
        NumberRange(min=0, max=9999999999, message="Max Amount must be between 0 and 9999999999.")
    ])
    
    image = FileField('', validators=[Optional(),FileAllowed(['jpg', 'jpeg', 'png'], INVALID_Image_MESSAGE)])

   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_subPaymentModeType(self, field):
        existing = SubPaymentModes.objects(subPaymentModeType=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Sub Payment Mode already exists.')      
        
    def validate_paymentModeId(self, field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid paymentModeId format.")
        payments_mods_queryset = PaymentMode.objects(id=field.data,status__in=[0,1]).order_by("-id")
        if not payments_mods_queryset:
            raise ValidationError("Selected payment Mode is not valid.")

    


class SubPaymentModeFormSearch(FlaskForm):
    subPaymentModeType = StringField('', validators=[
        Optional(),
        Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE),
        Regexp(ALPHANUMERIC_REGEX, message="Sub Payment Mode must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")
    ])
    paymentModeId = SelectField('', choices=[], validate_choice=False)  # optional
    

    def validate_paymentModeId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid paymentmode format.")

    class Meta:
        csrf = False


class RegionsForm(FlaskForm):
    regionName = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    regionType = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_regionName(self, field):
        existing = Regions.objects(regionName=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Region Name already exists.')

    def validate_regionType(self, field):
        existing = Regions.objects(regionType=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Region Type already exists.')

class RegionsFormSearch(FlaskForm):
    regions_search_element = StringField('',validators=[Optional(),
            Length(min=MIN_LENGTH_3,max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE),
            
            Regexp(ALPHANUMERIC_REGEX, message=("Search field must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / ."))])
    
    class Meta:
        csrf = False

class CountriesForm(FlaskForm):
    countryName = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    countryCode = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_2, max=4, message=INVALID_LENGTH_MESSAGE), Regexp(COUNTRY_CODE, message=INVALID_FORMAT_MESSAGE)])
    regionId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    regex = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE), Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    countryFlag = FileField('', validators=[Optional(),FileAllowed(['jpg', 'jpeg', 'png'], INVALID_Image_MESSAGE)])

   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)
        
    def validate_countryName(self, field):
        existing = Countries.objects(countryName=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Country Name already exists.')

    def validate_countryCode(self, field):
        existing = Countries.objects(countryCode=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Country Code already exists.')

        
    def validate_regionId(self, field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Region Id format.")
        regions_queryset = Regions.objects(id=field.data,status__in=[0,1]).order_by("-id")
        if not regions_queryset:
            raise ValidationError("Selected Region Id is not valid.")

class CountriesFormSearch(FlaskForm):
    countries_search_element = StringField('',validators=[Optional(),
            Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE),
            Regexp(ALPHANUMERIC_REGEX, message=("Search field must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / ."))])
        
    class Meta:
        csrf = False   
class StatesForm(FlaskForm):
    stateName = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    countryId = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    stateCode = StringField('', validators=[DataRequired(), Length(min=1, max=2,message=INVALID_LENGTH_MESSAGE),Regexp(STATE_CODE_REGEX, message=INVALID_FORMAT_MESSAGE)])
    
   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_stateName(self, field):
        existing = States.objects(stateName=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('State Name already exists.')
    def validate_stateCode(self, field):
        existing = States.objects(stateCode=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('State Code already exists.')


class StatesFormSearch(FlaskForm):
    states_search_element = StringField('',validators=[Optional(),
            Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE),
            Regexp(ALPHANUMERIC_REGEX, message=("Search field must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / ."))])
        
    class Meta:
        csrf = False  

class CitiesForm(FlaskForm):
    cityName = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    stateId = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_cityName(self, field):
        existing = Cities.objects(cityName=field.data, status__in=[0,1]).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('City Name already exists.')

class CititesFormSearch(FlaskForm):
    cities_search_element = StringField('',validators=[Optional(),
            Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE),
            Regexp(ALPHANUMERIC_REGEX, message=("Search field must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / ."))])
        
    class Meta:
        csrf = False 

class BlocksForm(FlaskForm):
    name = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    cityId = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_name(self, field):
        existing = BlocksPos.objects(name=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Block/PO Name already exists.')
        
class BlocksFormSearch(FlaskForm):
    blocks_search_element = StringField('',validators=[Optional(),
            Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE),
            Regexp(ALPHANUMERIC_REGEX, message=("Search field must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / ."))])
        
    class Meta:
        csrf = False 

class PincodesForm(FlaskForm):
    pincode = IntegerField('', validators=[DataRequired(), NumberRange(min=100000, max=999999,message=INVALID_LENGTH_MESSAGE)])
    blockPoId = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    lat = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=11, message=INVALID_LENGTH_MESSAGE), Regexp(r"^-?(90(\.0{1,6})?|[0-8]?[0-9](\.[0-9]{1,6})?)$", message="Invalid latitude! Must be between -90 and 90, with up to 6 decimal places.")])
    long = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=11, message=INVALID_LENGTH_MESSAGE), Regexp(r"^-?(180(\.0{1,6})?|1[0-7][0-9](\.[0-9]{1,6})?|[0-9]{1,2}(\.[0-9]{1,6})?)$", message="Invalid longitude! Must be between -180 and 180, with up to 6 decimal places.")])
   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_pincode(self, field):
        existing = Pincodes.objects(pincode=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Pincode already exists.')
        
class PincodesFormSearch(FlaskForm):
    pincodes_search_element = StringField('',validators=[Optional(),
            Length(min=6, max=6, message=INVALID_LENGTH_MESSAGE),
            Regexp(ONLY_NUMERIC, message=("Pincode search accepts only numeric values"))])
        
    class Meta:
        csrf = False 



class ProfileForm(FlaskForm):
    name = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75),Regexp(r"^(?!\d+$)[a-zA-Z0-9\s@#$()+_\-/.]+$", message="Only alphanumeric and special characters @#$()+_-/")])
    rank = StringField('', validators=[DataRequired(), Regexp(r"^[1-9][0-9]{0,5}$", message="Rank must be a number between 1 and 999999")])
    description = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_1, max=MAX_LENGTH_150),Regexp(r"^(?=.*[a-zA-Z0-9])[\w\s\S]+$", message="Only alphanumeric and special characters @#$()+_-/")])
    code = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_1, max=MAX_LENGTH_15),Regexp(r"^[a-zA-Z0-9_\-\.]+$", message="Code can only contain letters, numbers.")])
    userPermissionId = SelectField('', choices=[],validate_choice=False, validators=[DataRequired()])
    # payinPaymentGatewaysList = SelectMultipleField('', choices=[],validate_choice=False, validators=[DataRequired()])
    defaultProfile = BooleanField('')
    payinEnable = BooleanField('')
    defaultPayinPaymentGatewayId = SelectField('', choices=[],validate_choice=False, validators=[Optional()])
    payoutEnable = BooleanField('')
    defaultPayoutPaymentGatewayId = SelectField('', choices=[],validate_choice=False, validators=[Optional()])
    remark = StringField('', validators=[Length(min=1,max=150),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])
    payoutPaymentGatewayId=SelectField('', choices=[],validate_choice=False, validators=[Optional()])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None

        if self.current_id:
            self.remark.validators.append(DataRequired())  # Make remark mandatory
        if self.payinEnable.data==True:
            # self.defaultPayinPaymentGatewayId.validators.append(DataRequired())
            self.defaultPayinPaymentGatewayId.validators = [
                v for v in self.defaultPayinPaymentGatewayId.validators if not isinstance(v, Optional)
            ]
            self.defaultPayinPaymentGatewayId.validators.append(DataRequired())
        if self.payoutEnable.data==True:
           
            if self.current_id:
                self.payoutPaymentGatewayId.validators = [
                    v for v in self.payoutPaymentGatewayId.validators if not isinstance(v, Optional)
                ]
                self.payoutPaymentGatewayId.validators.append(DataRequired())
            else:
                self.defaultPayoutPaymentGatewayId.validators = [
                v for v in self.defaultPayoutPaymentGatewayId.validators if not isinstance(v, Optional)
                ]
                self.defaultPayoutPaymentGatewayId.validators.append(DataRequired())
            

        if not self.current_id:
            del self.remark
        # self.process(*args, **kwargs)

    def validate_defaultPayinPaymentGatewayId(self, field):
        if self.payinEnable.data=="True":
            if not field.data:
                raise ValidationError("Please select a Payin Payment Gateway.")
        if field.data:
            pg = TransactionAPI.objects(id=field.data, transactionType="PaymentGateway", status__in=[0,1]).first()
            if not pg:
                raise ValidationError("Please select a valid Payin Payment Gateway.")

    def validate_defaultPayoutPaymentGatewayId(self, field):
        if not self.current_id and self.payoutEnable.data=="True":
            if not field.data:
                raise ValidationError("Please select a Payout Payment Gateway.")
        if field.data:
            pg = TransactionAPI.objects(id=field.data, transactionType="Payout",status__in=[0,1]).first()
            if not pg:
                raise ValidationError("Please select a valid Payout Payment Gateway.")

    def validate_payoutPaymentGatewayId(self, field):
        if self.current_id and self.payoutEnable.data=="True":
            if not field.data:
                raise ValidationError("Please select a Payout Payment Gateway.")
        if field.data:
            pg = TransactionAPI.objects(id=field.data, transactionType="Payout", status__in=[0,1]).first()
            if not pg:
                raise ValidationError("Please select a valid Payout Payment Gateway.")
    # def validate_payinPaymentGatewaysList(self,field):
    #     valid_count = TransactionAPI.objects(id__in=field.data,transactionType= "PaymentGateway",status__in=[0,1]).count()
    #     if valid_count != len(field.data):
    #         raise ValidationError("One or more selected APIs are invalid.")
        
    def validate_name(self, field):     
        existing = Patterns.objects(name=field.data, status__in=[0,1]).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Profile Name already exists!')
        
    def validate_code(self, field):     
        existing = Patterns.objects(code=field.data, status__in=[0,1]).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Code already exists!')

class ProfileSearchForm(FlaskForm):
    ProfileSearchElement = StringField('',validators=[Optional(),Length(min=MAX_LENGTH_3,max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/.]+$', message=("Search field must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / ."))])
    
    class Meta:
        csrf = False

class MerchantSetupChargeSearchForm(FlaskForm):
    patternId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message="Merchant Profile is required.")])
    paymentModeId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message="Payment Mode is required.")])
    instantSettlement = SelectField('', choices=[ ("","Select"),("True","True"),("False","False")],validators=[DataRequired(message="Instant Settlement Type is required.")])
    def validate_patternId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid Pattern Id.")
            pattern_queryset = Patterns.objects(id=field.data,status__in=[0,1]).first()
            if not pattern_queryset:
                raise ValidationError("Please select a valid Pattern Id.")
            
    def validate_paymentModeId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Payment Id.")
            payment_mode_queryset = PaymentMode.objects(id=field.data,status__nin=[2]).first()
            if not payment_mode_queryset:
                raise ValidationError("Please select a Valid Payment Id")
            
    class Meta:
        csrf = False


class ApiUpsertSetupChargeCommissionForm(FlaskForm):
    priceType = SelectField("", choices=["FIXED", "RANGE"], validators=[DataRequired()])
    startAmount = FloatField("", validators=[Optional(), NumberRange(min=0, max=9999999999, message="Amount must be between 0 and 9999999999.")])
    endAmount = FloatField("", validators=[Optional(), NumberRange(min=0, max=9999999999, message="Amount must be between 0 and 9999999999.")])
    isUnlimited = BooleanField("")
    chargeTypeList = SelectField("", choices=["FLAT","PERCENTAGE"], validators=[Optional()])
    chargeValueList = FloatField("", validators=[Optional(), NumberRange(min=0, max=9999999999, message="Charge Value must be between 0 and 9999999999.")])
    chargeType = SelectField("", choices=["FLAT","PERCENTAGE"], validators=[Optional()])
    # startAmountListField = FieldList(FloatField("", validators=[Optional()]))
    # endAmountListField = FieldList(FloatField("", validators=[Optional()]))
    # chargeTypeListField = FieldList(FloatField("", validators=[Optional()]))
    # chargeValueListField = FieldList(FloatField("", validators=[Optional()]))
    chargeValue = FloatField("", validators=[Optional(), NumberRange(min=0, max=9999999999, message="Charge Value must be between 0 and 9999999999.")])
    readonlyPrice = FloatField("", validators=[Optional()])
    gstInclude = SelectField("", choices=["Yes", "No"], validators=[DataRequired()])
    gstValue = FloatField("", validators=[InputRequired(), NumberRange(min=0, max=100, message="GST Value must be between 0 and 100.")])
    tdsInclude = SelectField("", choices=["Yes", "No"], validators=[DataRequired()])
    tdsValue = FloatField("", validators=[InputRequired(), NumberRange(min=0, max=100, message="TDS Value must be between 0 and 100.")])
    
    

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        # self.current_id = str(current_id) if current_id else None
        if self.priceType.data == "FIXED":
            self.chargeType.validators.append(DataRequired())
            self.chargeValue.validators.append(InputRequired())
        else:
            del self.chargeType
            del self.chargeValue

        # if self.priceType.data == "RANGE":
        #     self.endAmount.validators.append(InputRequired())
        #     self.chargeTypeList.validators.append(DataRequired())
        #     self.chargeValueList.validators.append(InputRequired())

        #     # if self.endAmount <= self.startAmount:
        #     #     raise ValidationError("end amount must be greater than start amount")

        #     # for i in range(len(self.startAmountListField)):
        #     #     if self.startAmountListField[ i + 1 ] - self.endAmountListField[ i ] > 0.10:
        #     #         raise ValidationError("start amount must not exceed the previous end amount by more than 0.10.")
        # else:
        #     del self.endAmount
        #     del self.chargeTypeList
        #     del self.chargeValueList

    class Meta:
        csrf = False

  
class GetApiSetupChargeCommissionListFormList(FlaskForm):
    paymentModeId = SelectField('', choices=[],validate_choice=False , validators=[DataRequired(message="Payment Mode is required")])
    transactionAPIId = SelectField('', choices=[],validate_choice=False , validators=[DataRequired(message="Transaction API is required")])

    class Meta:
        csrf = False

class ApiSetupChargeSearchForm(FlaskForm):
    paymentModeId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message="Payment Mode is required.")])
    transactionAPIId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message="TransactionApi is required.")])
    holidayPrice = SelectField('', choices=[ ("","Select"),("True","True"),("False","False")],validators=[DataRequired(message="HolidayPrice is required.")])
    def validate_patternId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid Pattern Id.")
            transaction_api_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1]).first()
            if not transaction_api_queryset:
                raise ValidationError("Please select a valid Transaction Api Id.")
            
    def validate_paymentModeId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Payment Id.")
            payment_mode_queryset = PaymentMode.objects(id=field.data,status__nin=[2]).first()
            if not payment_mode_queryset:
                raise ValidationError("Please select a Valid Payment Id")
            
    class Meta:
        csrf = False

class PaymentSetupChargeSearchForm(FlaskForm):
    paymentModeId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message="Payment Mode is required.")])
    servicePaymentType = SelectField('', choices=["","bbps","digitalGold"] , validators=[DataRequired(message="Transaction API is required")])
    # def validate_patternId(self, field):
    #     if field.data:
    #         if not ObjectId.is_valid(field.data):
    #             raise ValidationError("Invalid Pattern Id.")
    #         transaction_api_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1]).first()
    #         if not transaction_api_queryset:
    #             raise ValidationError("Please select a valid Transaction Api Id.")
            
    def validate_paymentModeId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Payment Id.")
            payment_mode_queryset = PaymentMode.objects(id=field.data,status__nin=[2]).first()
            if not payment_mode_queryset:
                raise ValidationError("Please select a Valid Payment Id")
            
    class Meta:
        csrf = False

class GetApiSetupChargeCommissionListForm(FlaskForm):
    paymentModeId = SelectField('', choices=[],validate_choice=False , validators=[DataRequired()])
    transactionAPIId = SelectField('', choices=[],validate_choice=False , validators=[DataRequired()])

    class Meta:
        csrf = False

class OnDemandSettlementChargesForm(FlaskForm):
    chargeName = StringField('', validators=[DataRequired(message="Charge Name is Required"), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message="Please enter a Bank name between 3 and 75 characters"),Regexp(ALPHANUMERIC_REGEX, message="Charge can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    paymentGatewayIdsList = SelectMultipleField('', choices=[],validate_choice=False, validators=[DataRequired()])
    holidayCalculation = BooleanField('', validators=[Optional()])
    maxDays = IntegerField('', validators=[
        DataRequired(),
        NumberRange(min=0, max=9999, message="maxDays must be between 0 and 9999.")
    ])
    priceType = SelectField("", choices=["FIXED", "RANGE"], validators=[DataRequired()])
    chargeType = SelectField("", choices=["FLAT","PERCENTAGE"], validators=[DataRequired()])
    chargeValue = FloatField("", validators=[DataRequired(), NumberRange(min=0, max=9999999999, message="Max Amount must be between 0 and 9999999999.")])
    gstInclude = SelectField("", choices=["True", "False"], validators=[DataRequired()])
    gstValue = FloatField("", validators=[DataRequired(), NumberRange(min=0, max=9999999999, message="Max Amount must be between 0 and 9999999999.")])
    tdsInclude = SelectField("", choices=["True", "False"], validators=[DataRequired()])
    tdsValue = FloatField("", validators=[DataRequired(), NumberRange(min=0, max=9999999999, message="Max Amount must be between 0 and 9999999999.")])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
    
    def validate_chargeName(self, field):
        name_check = OnDemandSettlementCharges.objects(chargeName=field.data,status__in=[0,1]).first()
        if name_check and str(name_check.id) != self.current_id:
            raise ValidationError("Charge Name Already Exists")

    def validate_paymentGatewayIdsList(self, field):
        valid_count = TransactionAPI.objects(id__in=field.data,status__in=[0,1]).count()
        if valid_count != len(field.data):
            raise ValidationError("One or more selected APIs are invalid.")

class ServiceChargesForm(FlaskForm):
    chargeName = StringField("", validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE), Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    chargeType = SelectField(
        "",
        choices=[
            ('benificiaryValidation', 'benificiaryValidation'),
            ('AadharValidation', 'AadharValidation'),
            ('PanValidation', 'PanValidation'),
            ('GST', 'GST'),
            ('Pan with GST', 'Pan with GST'),
            ('Name Match', 'Name Match'),
            ('Bin Check', 'Bin Check'),
            ('Bank', 'Bank'),
            ('VideoKyc', 'video Kyc'),
            ('BbpsCharges', 'Bbps Charges'),
            ('DigitalGoldCharges', 'Digital Gold Charges'),
            ('PrepaidCharges', 'Prepaid Charges'),
        ],
        validators=[DataRequired()])
    amountType = SelectField("", choices=[('Percentage', 'Percentage'), ('Flat', 'Flat')], validators=[DataRequired()])
    amount = StringField("", validators=[DataRequired(),  Length(min=1, max=10,message=INVALID_LENGTH_MESSAGE),Regexp(DECIMALPOINT_REGEX, message=INVALID_FORMAT_MESSAGE)])
    gstInclude = SelectField("", choices=[('Yes', 'Yes'), ('No', 'No')], validators=[DataRequired()])
    gstValue = StringField("", validators=[Optional(), Length(min=1, max=3,message=INVALID_LENGTH_MESSAGE),Regexp(DECIMALPOINT_REGEX, message=INVALID_FORMAT_MESSAGE)])
    tdsInclude = SelectField("", choices=[('Yes', 'Yes'), ('No', 'No')], validators=[DataRequired()])
    tdsValue = StringField("", validators=[Optional(),  Length(min=1, max=3,message=INVALID_LENGTH_MESSAGE), Regexp(DECIMALPOINT_REGEX, message=INVALID_FORMAT_MESSAGE)])
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
    def validate_amount(self, field):
    
        if self.amountType.data == "Percentage":
            if field.data is None:
                raise ValidationError("Please enter amount")
            x = float(field.data)
            if not (x>=0 and x<= 100):
                raise ValidationError("Amount must be between 0 and 100 for percentage type")

class serviceFormSearch(FlaskForm):
    search_element = StringField('',validators=[Optional(),
            Length(min=MIN_LENGTH_3,max=MAX_LENGTH_75, message="The search field must be between 3 and 75 characters long."),
            Regexp(ALPHANUMERIC_REGEX, message="The search field can only contain letters, numbers, spaces, and the following special characters: @, #, $, (, ), +, _, -, /, .")])
    class Meta:
        csrf = False
        
class BulkProfileUpdateForm(FlaskForm):
    existingPatternIdsList=SelectMultipleField('', choices=[], validate_choice=False,validators=[DataRequired()])
    newPatternId=SelectField('', choices=[], validate_choice=False,validators=[DataRequired()])
    manageRadioButton=RadioField('Status', choices=[('includeButton', 'includeButton'), ('excludeButton', 'excludeButton')], validators=[Optional()])
    includeUsersList=SelectMultipleField('', choices=[], validate_choice=False,validators=[Optional()])
    excludeUsersList=SelectMultipleField('', choices=[], validate_choice=False,validators=[Optional()])

    def validate_existingPatternIdsList(self, field):
        if len(field.data) <= 0 :
            raise ValidationError("Existing Profile cannot be empty.")
        valid_count = Patterns.objects(id__in=field.data, status__nin=[2]).count()
        if valid_count != len(field.data):
            raise ValidationError("One or more selected Profile are invalid.")
        
    def validate_newPatternId(self, field):

        valid_count = Patterns.objects(id=field.data, status__ne=2).first()
        if field.data is None:
            raise ValidationError("New Profile cannot be empty")
        if not valid_count:
            raise ValidationError("Selected Profile is invalid")
        if not ObjectId.is_valid(field.data): 
            raise ValidationError("Invalid pattern Id")
        
    def validate_includeUsersList(self, field):
        # if len(field.data) <= 0 :
            # raise ValidationError("Include Users cannot be empty.")
        valid_count = Users.objects(id__in=field.data, status__nin=[2]).count()
        if valid_count != len(field.data):
            raise ValidationError("One or more selected users are invalid.")
        
    def validate_excludeUsersList(self, field):
        # if len(field.data) <= 0 :
            # raise ValidationError("Exclude Users cannot be empty.")
        valid_count = Users.objects(id__in=field.data, status__nin=[2]).count()
        if valid_count != len(field.data):
            raise ValidationError("One or more selected users are invalid.")
    
    class Meta:
        csrf = False

class BulkPayoutUpdateForm(FlaskForm):
    existingPayoutsIdsList=SelectMultipleField('', choices=[], validate_choice=False)
    newApiId=SelectField('', choices=[], validate_choice=False)
    manageRadioButton=RadioField('Status', choices=[('includeButton', 'includeButton'), ('excludeButton', 'excludeButton')], validators=[Optional()])
    includeProfilesList=SelectMultipleField('', choices=[], validate_choice=False)
    excludeProfilesList=SelectMultipleField('', choices=[], validate_choice=False)

    def validate_existingPayoutsIdsList(self, field):
        if len(field.data) <= 0 :
            raise ValidationError("Existing Payout cannot be empty.")
        valid_count = TransactionAPI.objects(id__in=field.data,transactionType="Payout", status__nin=[2]).count()
        if valid_count != len(field.data):
            raise ValidationError("One or more selected Payout's are invalid.")
        
    def validate_newApiId(self, field):
        if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid pattern Id.")
        if len(field.data) <= 0 :
            raise ValidationError("New Payout cannot be empty.")
        valid_count = TransactionAPI.objects(id=field.data, transactionType="Payout",status__ne=2).first()
        if not valid_count:
            raise ValidationError("Selected Payout is invalid.")
        
    def validate_includeProfilesList(self, field):
        # if len(field.data) <= 0 :
            # raise ValidationError("Include Users cannot be empty.")
        valid_count = Patterns.objects(id__in=field.data, status__nin=[2]).count()
        if valid_count != len(field.data):
            raise ValidationError("One or more selected Patterns are Invalid.")
        
    def validate_excludeProfilesList(self, field):
        # if len(field.data) <= 0 :
            # raise ValidationError("Exclude Users cannot be empty.")
        valid_count = Patterns.objects(id__in=field.data, status__nin=[2]).count()
        if valid_count != len(field.data):
            raise ValidationError("One or more selected Patterns are Invalid.")
    
    class Meta:
        csrf = False


class TimeRangeForm(FlaskForm):
    from_time = TimeField('', format="%H:%M", validators=[
        Optional(), Regexp(TIME_PATTERN, message="Enter time in 24-hour format (HH:MM)")])
    to_time = TimeField('', format="%H:%M", validators=[
        Optional(), Regexp(TIME_PATTERN, message="Enter time in 24-hour format (HH:MM)")])


class AvailableTimingsForm(FlaskForm):
    transactionType = SelectField('', choices=[
        ("payout", "Payout"), ("paymentgateway", "Payment Gateway")], validators=[Optional()])
    siteId = SelectField('', choices=[], validate_choice=False, validators=[Optional()])
    isEnabled = BooleanField("Enable All Timings")

    # Day-wise fields
    Sunday_is_enabled = BooleanField("Enable Sunday")
    sunAvailableTimingsList = FieldList(FormField(TimeRangeForm))

    Monday_is_enabled = BooleanField("Enable Monday")
    monAvailableTimingsList = FieldList(FormField(TimeRangeForm))

    Tuesday_is_enabled = BooleanField("Enable Tuesday")
    tueAvailableTimingsList = FieldList(FormField(TimeRangeForm))

    Wednesday_is_enabled = BooleanField("Enable Wednesday")
    wedAvailableTimingsList = FieldList(FormField(TimeRangeForm))

    Thursday_is_enabled = BooleanField("Enable Thursday")
    thuAvailableTimingsList = FieldList(FormField(TimeRangeForm))

    Friday_is_enabled = BooleanField("Enable Friday")
    friAvailableTimingsList = FieldList(FormField(TimeRangeForm))

    Saturday_is_enabled = BooleanField("Enable Saturday")
    satAvailableTimingsList = FieldList(FormField(TimeRangeForm))

    overridesDatesList = FieldList(StringField("Override Date", validators=[Optional()]))

    def validate_siteId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid Site Id.")
            # You may need to import and query your DB correctly
            site_queryset = MultipleAppSites.objects(id=field.data, status__nin=[2]).first()
            if not site_queryset:
                raise ValidationError("Please select a valid Site Id.")

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None

        day_mapping = [
            ("Sunday", "sun"),
            ("Monday", "mon"),
            ("Tuesday", "tue"),
            ("Wednesday", "wed"),
            ("Thursday", "thu"),
            ("Friday", "fri"),
            ("Saturday", "sat"),
        ]

        # Check if global enable is checked
        all_enabled = self.isEnabled.data

        for full_day, short_day in day_mapping:
            day_enabled = getattr(self, f"{full_day}_is_enabled")
            timing_list = getattr(self, f"{short_day}AvailableTimingsList")

            # If all enabled or individual day is enabled
            if all_enabled or day_enabled.data:
                # Make checkbox required
                day_enabled.validators = [v for v in day_enabled.validators if not isinstance(v, Optional)]
                day_enabled.validators.append(DataRequired())

                for timing_form in timing_list.entries:
                    # from_time
                    timing_form.from_time.validators = [
                        v for v in timing_form.from_time.validators if not isinstance(v, Optional)
                    ]
                    timing_form.from_time.validators.append(
                        DataRequired(message=f"{full_day} From Time is required")
                    )

                    # to_time
                    timing_form.to_time.validators = [
                        v for v in timing_form.to_time.validators if not isinstance(v, Optional)
                    ]
                    timing_form.to_time.validators.append(
                        DataRequired(message=f"{full_day} To Time is required")
                    )

class AddHolidayDateForm(FlaskForm):
    overrideDate = DateField('',format='%Y-%m-%d',validators=[DataRequired(message="Override Date is required")])
    from_time = FieldList(
        TimeField(
            '',
            format="%H:%M",
            validators=[
                DataRequired(message="From Time is required"),
                Regexp(TIME_PATTERN, message="Enter time in 24-hour format (HH:MM)")
            ]
        ),

    )
    to_time = FieldList(
        TimeField('', format="%H:%M", validators=[
        DataRequired(message="To Time is required"), Regexp(TIME_PATTERN, message="Enter time in 24-hour format (HH:MM)")])
    )

    class Meta:
        csrf = False

class AddNewUserForm(FlaskForm):
    fullName = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    phoneNumber =  StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_10, max=MIN_LENGTH_10),Regexp(PHONE_NUMBER_REGEX, message="Only Numbers allowed  with 1 to 10 digits.")])
    email = StringField('', validators=[DataRequired(),Length(min=6, max=100),Regexp(CONTACT_EMAIL_REGEX,  message="Please enter a valid email address.")])
    password = StringField('', validators=[DataRequired(),Length(min=6, max=30),Regexp(PASSWORD_REGEX, message="Password must be 6-30 characters long, include at least one uppercase letter, one lowercase letter, one number, and one special character.")])
    patternId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    entityTypeId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    address = StringField('', validators=[DataRequired(), Length(min=6, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    stateId =SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    cityId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    blockPoId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    pincodeId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    merchantType =SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    maxPayinLimit = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_1, max=MIN_LENGTH_10, message=INVALID_LENGTH_MESSAGE),Regexp(ONLY_NUMERIC, message="Only Numbers allowed  with 1 to 10 digits.")])
    maxPayoutLimit = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_1, max=MIN_LENGTH_10, message=INVALID_LENGTH_MESSAGE),Regexp(ONLY_NUMERIC, message="Only Numbers allowed  with 1 to 10 digits.")])
    siteTitle = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    remark = StringField('', validators=[DataRequired(), Length(min=1, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        if self.current_id:
            self.password.validators = [Optional()]
        else:
            self.remark.validators = [Optional()]
    
    def validate_phoneNumber(self, field):
        existing = Users.objects(phoneNumber=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Phone Number already exists.')
    
    def validate_email(self, field):
        existing = Users.objects(email=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Email already exists.')
        
    def validate_patternId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Pattern ID format.")
        
        patterns_queryset =  Patterns.objects(id=field.data,status__in=[0,1]).first()
        if not patterns_queryset:
            raise ValidationError("Selected Profile is not valid.")
        
    def validate_entityTypeId(self, field):
      
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Entity Type format.")
        entity_queryset =  UserEntity.objects(id=field.data,status__in=[0,1]).first()
        if not entity_queryset:
            raise ValidationError("Selected Entity Type is not valid.")
    
    def validate_stateId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid State ID format.")
        states_queryset =  States.objects(id=field.data,status__in=[0,1]).first()
        if not states_queryset:
            raise ValidationError("Selected State is not valid.")
        
    def validate_cityId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid City ID format.")
        cities_queryset =  Cities.objects(id=field.data,status__in=[0,1]).first()
        if not cities_queryset:
            raise ValidationError("Selected City is not valid.")
        
    def validate_blockPoId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Block/PO ID format.")
        blockpos_queryset =  BlocksPos.objects(id=field.data,status__in=[0,1]).first()
        if not blockpos_queryset:
            raise ValidationError("Selected Block/PO is not valid.")
    
    def validate_pincodeId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Pincode ID format.")
        pincodes_queryset =  Pincodes.objects(id=field.data,status__in=[0,1]).first()
        if not pincodes_queryset:
            raise ValidationError("Selected Pincode is not valid.")

        
class PersonalDetails(FlaskForm):
    fullName = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    phoneNumber =  StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_10, max=MIN_LENGTH_10),Regexp(PHONE_NUMBER_REGEX, message="Only Numbers allowed  with 1 to 10 digits.")])
    email = StringField('', validators=[DataRequired(),Length(min=6, max=100),Regexp(CONTACT_EMAIL_REGEX,  message="Please enter a valid email address.")])
    address = StringField('', validators=[DataRequired(), Length(min=6, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/,\.]*$', message=INVALID_FORMAT_MESSAGE)])
    remark = StringField('', validators=[DataRequired(), Length(min=1, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])

class AgreementDocumentForm(FlaskForm):
    agreementVerificationStatus = SelectField('', choices=["Submitted","Rejected","Pending","Approved"],validate_choice=True , validators=[DataRequired()])
    agreementVerificationReason = StringField('', validators=[DataRequired(), Length(min=1, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])

class VideoVerificationForm(FlaskForm):
    uploadVideo =FileField('', validators=[Optional(),FileAllowed(['mp4'], INVALID_Image_MESSAGE)])
    videoVerificationStatus = SelectField('', choices=["Submitted","Rejected","Pending","Approved"],validate_choice=True , validators=[DataRequired()])
    videoVerificationReason = StringField('', validators=[DataRequired(), Length(min=1, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    
class VideoVerificationDetailsForm(FlaskForm):
    uploadVideo =FileField('', validators=[Optional(),FileAllowed(['mp4'], INVALID_Image_MESSAGE)])
    videoVerificationStatus = SelectField('', choices=["Submitted","Rejected","Pending","Approved"],validate_choice=True , validators=[DataRequired()])
    videoVerificationRemark = StringField('', validators=[DataRequired(), Length(min=1, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])

class IdProofForm(FlaskForm):
    panDocument =  FileField('', validators=[Optional(),FileAllowed(['jpeg',"jpg", "pdf"], INVALID_Image_MESSAGE)])
    panStatus = SelectField('', choices=["Submitted","Rejected","Pending","Approved"],validate_choice=True , validators=[DataRequired()])
    panReason = StringField('', validators=[DataRequired(), Length(min=1, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])

class AadhaarProofForm(FlaskForm):
    aadharDocument =  FileField('', validators=[Optional(),FileAllowed(['jpeg',"jpg", "pdf"], INVALID_Image_MESSAGE)])
    aadharBackDocument =  FileField('', validators=[Optional(),FileAllowed(['jpeg',"jpg", "pdf"], INVALID_Image_MESSAGE)])
    aadharStatus = SelectField('', choices=["Submitted","Rejected","Pending","Approved"],validate_choice=True , validators=[DataRequired()])
    aadharReason = StringField('', validators=[DataRequired(), Length(min=1, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])

class BankVerificationForm(FlaskForm):
    bankStatus = SelectField('', choices=["Submitted","Rejected","Pending","Approved"],validate_choice=True , validators=[DataRequired()])
    bankReason = StringField('', validators=[DataRequired(), Length(min=1, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])

class BussinessForm(FlaskForm):
    businessStatus = SelectField('', choices=["Submitted","Rejected","Pending","Approved"],validate_choice=True , validators=[DataRequired()])
    businessRemark = StringField('', validators=[DataRequired(), Length(min=1, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])

class UploadDocumentForm(FlaskForm):
    documentStatus = SelectField('', choices=["Submitted","Rejected","Pending","Approved"],validate_choice=True , validators=[DataRequired()])
    documentRemark = StringField('', validators=[DataRequired(), Length(min=1, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])

class ShopImagesForm(FlaskForm):
    shopImageStatus = SelectField('', choices=["Submitted","Rejected","Pending","Approved"],validate_choice=True , validators=[DataRequired()])
    shopRemark = StringField('', validators=[DataRequired(), Length(min=1, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])

class ShopVideoForm(FlaskForm):
    shopVideo =FileField('', validators=[Optional(),FileAllowed(['mp4'], INVALID_Image_MESSAGE)])
    shopVideoStatus = SelectField('', choices=["Submitted","Rejected","Pending","Approved"],validate_choice=True , validators=[DataRequired()])
    videoVerificationRemark = StringField('', validators=[DataRequired(), Length(min=1, max=100,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])


class MerchantManagementSearchForm(FlaskForm):
    merchantId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MIN_LENGTH_10),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric characters are allowed")])
    merchantEmail = StringField('', validators=[Optional(),Length(min=6, max=100),Regexp(EMAIL_REGEX, message="Only Email format aab@efg.com is allowed")])
    merchantName = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])
    merchantPhone =  StringField('', validators=[Optional(),Length(min=MIN_LENGTH_1, max=MIN_LENGTH_10),Regexp(PHONE_NUMBER_REGEX, message="Only Numbers allowed  with 1 to 10 digits.")])
    parentId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    patternId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantType = SelectField('', choices=[
        ("",""),
        ("Super Distributor","Super Distributor"),
        ("Master Distributor","Master Distributor"),
        ("Area Distributor","Area Distributor"),
        ("Retailer","Retailer"),
        ("customer","customer")
        ],validators=[Optional()])
    siteTitle = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    stateId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])

    def validate_parentId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid Parent Id Id.")
            users_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not users_queryset:
                raise ValidationError("Please select a Parent Id Id")
            
    def validate_patternId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid Pattern Id.")
            pattern_queryset = Patterns.objects(id=field.data,status__in=[0,1]).first()
            if not pattern_queryset:
                raise ValidationError("Please select a valid Pattern Id.")
            
    def validate_siteTitle(self, field):
        if field.data:
            mulappsites_queryset = MultipleAppSites.objects(siteCode=field.data,status__in=[0,1]).first()
            if not mulappsites_queryset:
                raise ValidationError("Please select a valid Site Title.")
            
    def validate_stateId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid State Id.")
            states_queryset = States.objects(id=field.data,status__in=[0,1]).first()
            if not states_queryset:
                raise ValidationError("Please select a valid State Id.")

    class Meta:
        csrf = False

class viewparentForm(FlaskForm):
    parentId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    remark = StringField('', validators=[DataRequired(),Length(min=1,max=150),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])
    userId = StringField('',validators=[DataRequired()])
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        
    def validate_parentId(self, field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid parent format.")
        parents_dropdown_queryset =  Users.objects(id=field.data,status__in=[0,1]).first()
        if not parents_dropdown_queryset:
            raise ValidationError("Selected parent is not valid.")

class viewChildForm(FlaskForm):
    childId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    remark = StringField('', validators=[DataRequired(),Length(min=1,max=150),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])
    userId = StringField('',validators=[DataRequired()])
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        
    def validate_childId(self, field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid child format.")
        childs_dropdown_queryset =  Users.objects(id=field.data,status__in=[0,1]).first()
        if not childs_dropdown_queryset:
            raise ValidationError("Selected child is not valid.")
        
class CapBalanceForm(FlaskForm):
    capBalance = StringField("", validators=[DataRequired(),Regexp(r"^\s*₹?(\d{1,3})(,\d{3})*(\.\d{1,2})?\s*$", message="Cap Balance must be numeric")])
    remark = StringField('', validators=[DataRequired(),Length(min=1,max=150),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])
    
    class Meta:
        csrf = False

        
class PendingKycSearchForm(FlaskForm):
    merchantId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MIN_LENGTH_10),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric characters are allowed")])
    merchantEmail = StringField('', validators=[Optional(),Length(min=6, max=100),Regexp(EMAIL_REGEX, message="Only Email format aab@efg.com is allowed")])
    merchantName = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])
    merchantPhone =  StringField('', validators=[Optional(),Length(min=MIN_LENGTH_1, max=MIN_LENGTH_10),Regexp(PHONE_NUMBER_REGEX, message="Only Numbers allowed with 1 to 10 digits.")])
    parentId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    # patternId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    kycStatus = SelectField('', choices=[
        ("All","All"),("Rejected","Rejected"),("Pending","Pending"),("Retailer","Retailer"),("Submitted","Submitted")
        ],validators=[Optional()], coerce=str)
    merchantType = SelectField('', choices=[
        ("",""),
        ("Super Distributor","Super Distributor"),
        ("Master Distributor","Master Distributor"),
        ("Area Distributor","Area Distributor"),
        ("Retailer","Retailer"),
        ("customer","customer")
        ],validators=[Optional()])
    siteTitle = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    stateId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])

    def validate_parentId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid Parent Id Id.")
            users_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not users_queryset:
                raise ValidationError("Please select a Parent Id Id")
            
    def validate_siteTitle(self, field):
        if field.data:
            mulappsites_queryset = MultipleAppSites.objects(siteCode=field.data,status__in=[0,1]).first()
            if not mulappsites_queryset:
                raise ValidationError("Please select a valid Site Title.")
            
    def validate_stateId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid State Id.")
            states_queryset = States.objects(id=field.data,status__in=[0,1]).first()
            if not states_queryset:
                raise ValidationError("Please select a valid State Id.")

    class Meta:
        csrf = False

class BlockedUsersForm(FlaskForm):
    merchantId = StringField('', validators=[Optional(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_15,message = "Merchant id length in between 3 to 15 only"),Regexp(ALPHANUMERIC_WITHOUT_SPECIAL_CHARACTERS,message= "Merchant id must contain alpha numeric only") ])
    merchantName = StringField('', validators=[ Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message = "Merchant name length in between 3 to 15 only"),Regexp(ALPHANUMERIC_REGEX,message="Merchant name must contain only alphanumeric characters and @#$()+_-/ allowed") ])
    merchantEmail = StringField('', validators=[ Optional(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_32,message = "Merchant email length in between 1 to 32 only"),Regexp(EMAIL_REGEX,message="Merchant email must contain only alphanumeric characters and valid special characters like @#$()+_-/. allowed")])
    merchantPhone  = StringField('', validators=[ Optional(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_10,message = "Phone number must be 1 and 10 digits only"),Regexp(PHONE_NUMBER_REGEX,message="Phone number must be in numeric and 1 and 10 digits only")])

    class Meta:
        csrf = False

class BlockedUserListFormRemark(FlaskForm):
    remark = StringField('', validators=[DataRequired(message="Remark Is Required"),Length(min=MIN_LENGTH_1, max=MAX_LENGTH_150, message="Remark Is must be 1 to 150"), Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/.")])
    def validate_remark(self, field):
        pass
    class Meta:
        csrf = False

class KycEntityForm(FlaskForm):
    entityType = StringField("Entity Type*", validators=[DataRequired(), Length(min=3, max=75,message="Please enter a Entity Type between 3 and 75 characters"), Regexp(ALPHANUMERIC_REGEX, message="Entity field must Contain only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    isIndividual = BooleanField("Is Individual", validators=[Optional()])
    isDefault = BooleanField("Is Default", validators=[Optional()])
    remark = StringField('', validators=[Length(min=1,max=150),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        if self.current_id:
            self.remark.validators.append(DataRequired())
        else:
            del self.remark 
    def validate_entityType(self, field):
        existing = UserEntity.objects(entityType=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('entityType already exists.')   
    
class entityFormSearch(FlaskForm):
    user_entity_search_element = StringField('',validators=[Optional(),Length(min=3, max=75,message="Please enter a Entity Type between 3 and 75 characters"), Regexp(ALPHANUMERIC_REGEX, message="Entity field must Contain only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    class Meta:
        csrf = False    

class BlockedUsersForm(FlaskForm):
    merchantId = StringField('', validators=[Optional(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_15,message = "Merchant id length in between 3 to 15 only"),Regexp(ALPHANUMERIC_WITHOUT_SPECIAL_CHARACTERS,message= "Merchant id must contain alpha numeric only") ])
    merchantName = StringField('', validators=[ Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message = "Merchant name length in between 3 to 15 only"),Regexp(ALPHANUMERIC_REGEX,message="Merchant name must contain only alphanumeric characters and @#$()+_-/ allowed") ])
    merchantEmail = StringField('', validators=[ Optional(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_32,message = "Merchant email length in between 1 to 32 only"),Regexp(EMAIL_REGEX,message="Merchant email must contain only alphanumeric characters and valid special characters like @#$()+_-/. allowed")])
    merchantPhone  = StringField('', validators=[ Optional(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_10,message = "Phone number must be 1 and 10 digits only"),Regexp(PHONE_NUMBER_REGEX,message="Phone number must be in numeric and 1 and 10 digits only")])

    class Meta:
        csrf = False

class BlockedUserListFormRemark(FlaskForm):
    remark = StringField('', validators=[DataRequired(message="Remark Is Required"),Length(min=MIN_LENGTH_1, max=MAX_LENGTH_150, message="Remark Is must be 1 to 150"), Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/.")])
    def validate_remark(self, field):
        pass
    class Meta:
        csrf = False

class BusinessDocumentForm(FlaskForm):
    name = StringField("", validators=[DataRequired(), Length(min=3, max=75,message="Please enter a Entity Type between 3 and 75 characters"), Regexp(ALPHANUMERIC_REGEX, message="Business Document Name must Contain only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    isRequired = BooleanField("", validators=[Optional()])
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None

    def validate_name(self, field):
        existing = BusinessDocuments.objects(name=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Document name already exists.')   
    
class BusinessFormSearch(FlaskForm):
    search_element = StringField('',validators=[Optional(),Length(min=3, max=75,message="Please enter a Document Type between 3 and 75 characters"), Regexp(ALPHANUMERIC_REGEX, message="Document field must Contain only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    class Meta:
        csrf = False    

class UserPayinPayoutForm(FlaskForm):
    usersListType = SelectField("",choices=[("All", "All"), ("Specific", "Specific")],validators=[DataRequired(message="Users List Type is required.")])
    usersList = SelectMultipleField('', choices=[], validate_choice=False)
    walletType = SelectField("",choices=[("Both", "Both"), ("Payin", "Payin"), ("Payout", "Payout")],validators=[DataRequired(message="Wallet Type is required.")])
    statusType = SelectField("",choices=[("True", "Enable"), ("False", "Disable")],validators=[DataRequired(message="Status Type is required.")])
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        
    def validate_usersList(self, field):
        if self.usersListType.data == "Specific":
            if not field.data:
                raise ValidationError("Users List is required when 'Specific' is selected.")
        
            valid_count = Users.objects(id__in=field.data, status__nin=[2]).count()
            if valid_count != len(field.data):
                raise ValidationError("One or more selected users are invalid.")
    class Meta:
        csrf = False


class CategoriesListForm(FlaskForm):
    name = StringField('',validators=[DataRequired(message="Name is required."),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="Name must be between 3 and 75 characters."), Regexp(ALPHANUMERIC_REGEX, message="Name can only contain alphanumeric characters and :@#$()+_-/.")])
    sorting = IntegerField('',validators=[InputRequired(message="Sorting is required."),NumberRange(min=1, max=9999, message="Sorting must be between 1 and 9999."),])
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
     
    def validate_name(self, field):     
        existing = ServiceGrouping.objects(name=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Category Name already exists')

class ServiceListForm(FlaskForm):
    categoryName = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="Category Name must be between 3 and 75 characters."),Regexp(ALPHANUMERIC_REGEX, message=" Category Name contains only alphanumeric and space and special characters @#$()+_-/")])
    serviceGroupingId = SelectField('',choices=[],validate_choice=False, validators=[DataRequired()])
    sorting = IntegerField('', validators=[Optional(),NumberRange(min=1, max=9999, message="Sorting must be between 1 and 9999")])
    isTpin = BooleanField('', validators=[Optional()])
    displayInDashboard = BooleanField('', validators=[Optional()])
    comingsoon = BooleanField('', validators=[Optional()])
    image = FileField('', validators=[Optional(),FileAllowed(['jpg', 'jpeg', 'png'], INVALID_Image_MESSAGE)])
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_serviceGroupingId(self, field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Category Name format.")
        categories_queryset =  ServiceGrouping.objects(id=field.data,status__in=[0,1]).first()
        if not categories_queryset:
            raise ValidationError("Selected Categeory Name is not valid.")
   
    def validate_categoryName(self, field):
        existing = Categories.objects(categoryName=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Category Name already exists.')
        

class ServiceFormSearch(FlaskForm):
    search_element = StringField('',validators=[Optional(),
            Length(min=MIN_LENGTH_3,max=MAX_LENGTH_75, message="Search field must be 3 to 75 characters"),
            Regexp(ALPHANUMERIC_REGEX, message="Search field must contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    class Meta:
        csrf = False


def file_size_limit(max_size_in_mb):
    max_bytes = max_size_in_mb * 1024 * 1024

    def _file_size_limit(form, field):
        if field.data:
            file = field.data
            file.seek(0, 2)  # Seek to the end of the file
            size = file.tell()
            file.seek(0)  # Reset file pointer to the start
            if size > max_bytes:
                raise ValidationError(f"Image size must be less than {max_size_in_mb}MB.")
    return _file_size_limit

class subserviceListForm(FlaskForm):
    serviceName=  StringField('',validators=[DataRequired(message="Sub Service Name is required."),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="Sub Service Name must be between 3 and 75 characters."), Regexp(ALPHANUMERIC_REGEX, message="Sub Service Name can only contain alphanumeric characters and :@#$()+_-/.")])
    serviceType=SelectField("",
        choices=[
            ('bbps', 'bbps'),
            ('digital-gold', 'digital-gold'),
            ('bus-ticket', 'bus-ticket'),
            ('movie-ticket', 'movie-ticket'),
            ('flight-ticket', 'flight-ticket'),
            ('mobile-prepaid', 'mobile-prepaid'),
            ('train-ticket', 'train-ticket'),
            ('metro-ticket', 'metro-ticket')
        ],validate_choice=True,
        validators=[DataRequired(message="Service Type is requried")])
    serviceGroupingIdsList = SelectMultipleField('',choices=[],validate_choice=False, validators=[DataRequired(message="Category Name is requried")])
    code = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_1, max=MAX_LENGTH_15),Regexp(ALPHANUMERIC_WITHOUT_SPECIAL_CHARACTERS, message="Code must contains only alphanumeric characters (letters, digits) and spaces.")])
    displayInDashboard = BooleanField('', validators=[Optional()])
    isService = BooleanField('', validators=[Optional()])
    isbbps = BooleanField('', validators=[Optional()])
    isOperatorWise = BooleanField('', validators=[Optional()])
    sorting = IntegerField('', validators=[Optional(),NumberRange(min=1, max=9999, message="Sorting must be between 1 and 9999")])
    image = FileField('', validators=[Optional(),FileAllowed(['jpg', 'jpeg', 'png'], INVALID_Image_MESSAGE),file_size_limit(1)])
    categoryIdsList = SelectMultipleField('', choices=[],validate_choice=False, validators=[DataRequired(message="Category is requried")])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)
   
    def validate_serviceName(self, field):
        existing = Service.objects(serviceName=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('service Name already exists.')
           
    def validate_categoryIdsList(self, field):
        valid_count = Categories.objects(id__in=field.data,status__in=[0,1]).count()
        if valid_count != len(field.data):
            raise ValidationError("One or more selected APIs are invalid.")
        
    def validate_serviceGroupingId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Category Name.")
    
        
    class Meta:
        csrf = False

class subserviceListForm(FlaskForm):
    serviceName=  StringField('',validators=[DataRequired(message="Sub Service Name is required."),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="Sub Service Name must be between 3 and 75 characters."), Regexp(ALPHANUMERIC_REGEX, message="Sub Service Name can only contain alphanumeric characters and :@#$()+_-/.")])
    serviceType=SelectField("",
        choices=[
            ('bbps', 'bbps'),
            ('digital-gold', 'digital-gold'),
            ('bus-ticket', 'bus-ticket'),
            ('movie-ticket', 'movie-ticket'),
            ('flight-ticket', 'flight-ticket'),
            ('mobile-prepaid', 'mobile-prepaid'),
            ('train-ticket', 'train-ticket'),
            ('metro-ticket', 'metro-ticket')
        ],validate_choice=True,
        validators=[DataRequired(message="Service Type is requried")])
    serviceGroupingIdsList = SelectMultipleField('',choices=[],validate_choice=False, validators=[DataRequired(message="Category Name is requried")])
    code = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_1, max=MAX_LENGTH_15),Regexp(ALPHANUMERIC_WITHOUT_SPECIAL_CHARACTERS, message="Code must contains only alphanumeric characters (letters, digits) and spaces.")])
    displayInDashboard = BooleanField('', validators=[Optional()])
    isService = BooleanField('', validators=[Optional()])
    isbbps = BooleanField('', validators=[Optional()])
    isOperatorWise = BooleanField('', validators=[Optional()])
    sorting = IntegerField('', validators=[Optional(),NumberRange(min=1, max=9999, message="Sorting must be between 1 and 9999")])
    image = FileField('', validators=[Optional(),FileAllowed(['jpg', 'jpeg', 'png'], INVALID_Image_MESSAGE),file_size_limit(1)])
    categoryIdsList = SelectMultipleField('', choices=[],validate_choice=False, validators=[DataRequired(message="Category is requried")])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)
   
    def validate_serviceName(self, field):
        existing = Service.objects(serviceName=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('service Name already exists.')
           
    def validate_categoryIdsList(self, field):
        valid_count = Categories.objects(id__in=field.data,status__in=[0,1]).count()
        if valid_count != len(field.data):
            raise ValidationError("One or more selected APIs are invalid.")
        
    def validate_serviceGroupingId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Category Name.")
    
        
    class Meta:
        csrf = False



class SearchSubServiceList(FlaskForm):
    search_element = StringField('',validators=[Optional(), Length(min=3, max=75,message="Sub Service Name Must contain between 3 and 75 characters"),Regexp(ALPHANUMERIC_REGEX, message="Sub Service Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    serviceType = SelectField('', choices=["","bbps", "digital-gold", "bus-ticket", "movie-ticket", "flight-ticket", "mobile-prepaid", "train-ticket", "metro-ticket"],validate_choice=True,validators=[Optional()])
        
    class Meta:
        csrf = False

class AddOperatorForm(FlaskForm):
    operatorName = StringField('', validators=[DataRequired(), Length(min=3, max=75,message="Name must contains between 3 and 75 characters"),Regexp(r"^[a-zA-Z0-9\s@#$()+_\-/]+$", message= "Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    allowType = StringField('', validators=[DataRequired(), Length(min=1, max=15,message="Allow Type must contains between 1 and 15 characters"),Regexp(r"^[a-zA-Z0-9\s]+$", message= "Allow Type must contain only alphanumeric characters (letters, digits) and spaces.")])
    transactionAPIId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Transaction API is required")])
    serviceId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Sub Service Name is required")])
    taxTypeId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Tax Type Name is required")])
    serviceGroupingId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Categories is required")])
    apiCode = StringField('', validators=[Optional(), Length(min=1, max=15,message="Api Code must contains between 1 and 15 characters"),Regexp(r"^[a-zA-Z0-9\s]+$", message= "Api Code contain only alphanumeric characters (letters, digits) and spaces.")])
    apiType = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    sorting = StringField('', validators=[Optional(), Length(min=1, max=10,message="Sorting must contains between 1 and 10 numeric characters"),Regexp(r"^\d+(\.\d+)?$", message= "Sorting must contain only numeric characters")])
    stateId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "State Name is required")])
    image = FileField('', validators=[Optional(),FileAllowed(['jpg', 'jpeg', 'png'], INVALID_Image_MESSAGE)])
    displayInDashboard = BooleanField('', validators=[Optional()])
    payWithoutFetchAllowed = BooleanField('', validators=[Optional()])
    isBbps = BooleanField('', validators=[Optional()])
    isValidate = BooleanField('', validators=[Optional()])
    
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_operatorName(self, field):
        existing = Operators.objects(operatorName=field.data, status__in=[0,1]).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Name already exists.')
        

    def validate_transactionAPIId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Transaction API Format .")
    
    def validate_serviceId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Sub Service Name.")
        
    def validate_taxTypeId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Tax Type Name .")
    
    def validate_serviceGroupingId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Categories.")
        
    def validate_stateId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid State Name.")
    
    
    class Meta:
        csrf = False

class SearchOperatorConfigurationsList(FlaskForm):
    search_element = StringField('',validators=[Optional(), Length(min=3, max=75,message="Operator Name Must contain between 3 and 75 characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message=" Operator Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])

    class Meta:
        csrf = False


class AddOperatorUpdateForm(FlaskForm):
    operatorId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message="Operator is required")])
    apiOperatorCode1 = StringField('',validators=[DataRequired(), Length(min=1, max=15,message="Api Operator Code1 must contains between 1 and 15 AlphaNumeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="ApiOperator Code1 must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    apiOperatorCode2 = StringField('',validators=[DataRequired(), Length(min=1, max=15,message="Api Operator Code2 must contains between 1 and 15 AlphaNumeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="ApiOperator Code2 must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    apiOperatorCode3 = StringField('',validators=[DataRequired(), Length(min=1, max=15,message="Api Operator Code3 must contains between 1 and 15 AlphaNumeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="ApiOperator Code3 must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    apiOperatorCode4 = StringField('',validators=[DataRequired(), Length(min=1, max=15,message="Api Operator Code4 must contains between 1 and 15 AlphaNumeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="ApiOperator Code4 must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    apiOperatorCode5 = StringField('',validators=[DataRequired(), Length(min=1, max=15,message="Api Operator Code5 must contains between 1 and 15 AlphaNumeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="ApiOperator Code5 must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    apiOperatorCode6 = StringField('',validators=[DataRequired(), Length(min=1, max=15,message="Api Operator Code6 must contains between 1 and 15 AlphaNumeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="ApiOperator Code6 must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    
    def validate_operatorId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Operator Name .")
    

    class Meta:
        csrf = False

class SearchOperatorUpdate(FlaskForm):
    search_element = StringField('',validators=[Optional(), Length(min=3, max=75,message="Api Operator Code1 Must contain between 3 and 75 characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="Api Operator Code1 must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])

    class Meta:
        csrf = False


class AddOperatorParameter(FlaskForm):
    displayName = StringField('', validators=[DataRequired(), Length(min=3, max=75,message="Display Name must contains between 3 and 75 characters"),Regexp(ALPHANUMERIC_REGEX, message= "Display Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    parameterName = StringField('', validators=[DataRequired(), Length(min=3, max=75,message="Parameter Name must contains between 3 and 75 characters"),Regexp(ALPHANUMERIC_REGEX, message= "Parameter Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    operatorId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Operator is required")])
    minLength = StringField('', validators=[DataRequired(), Length(min=1, max=10,message="Min Length must contains between 1 and 10 numeric characters"),Regexp(ONLY_NUMERIC, message= "Min Length must contain only numeric characters")])
    maxLength = StringField('', validators=[DataRequired(), Length(min=1, max=10,message="Max Length must contains between 1 and 10 numeric characters"),Regexp(ONLY_NUMERIC, message= "Max Length must contain only numeric characters")])
    sort = StringField('', validators=[Optional(), Length(min=1, max=10,message="Sort must contains between 1 and 10 numeric characters"),Regexp(ONLY_NUMERIC, message= "Sort must contain only numeric characters")])
    fieldType = SelectField('', choices=[("Input", "Input"), ("Number","Number"), ("DropDown", "Drop Down")],validate_choice=True,validators=[DataRequired(message = "Field Type is required")])
    pattern = StringField('', validators=[Optional(), Length(min=1, max=75,message="Pattern must contains between 1 and 75 characters"),Regexp(ALPHANUMERIC_REGEX, message= "Pattern must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    apiCode = StringField('', validators=[DataRequired(), Length(min=3, max=15,message="Api Code must contains between 3 and 15 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPECIAL_CHARACTERS, message= "Api Code contain only alphanumeric characters (letters, digits) and spaces.")])
    transactionAPIId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "TransactionAPI is required")])
    isActive = BooleanField('', validators=[Optional()])
    isMandatory = BooleanField('', validators=[Optional()])
    hasGrouping = BooleanField('', validators=[Optional()])
    hasIncludeApiCall= BooleanField('', validators=[Optional()])
    isReferenceKey = BooleanField('', validators=[Optional()])
    hasApiCall = BooleanField('', validators=[Optional()])
    hasSubParameters = BooleanField('', validators=[Optional()])
    apiCall = SelectField('', choices=[("", "select"), ("operator", "operator"),("plans","Plans") ],validate_choice=True,validators=[DataRequired(message = "Api Call is required")])

    def validate_operatorId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Operator Name.")
    
    def validate_transactionAPIId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Api Name.")


    class Meta:
        csrf = False

class SearchOperatorParameterList(FlaskForm):
    search_element = StringField('',validators=[Optional(), Length(min=3, max=75,message="Display Name Must contain between 3 and 75 characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message=" Display Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])

    class Meta:
        csrf = False

class AddOperatorGroupingForm(FlaskForm):
    groupName = StringField('',validators=[DataRequired(), Length(min=3, max=75,message="Group Name must contains between 3 and 75 numeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="Group Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    operatorId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message="Operator is required")])
    operatorParameterId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message="Operator Parameter is required ")])
    value = StringField('',validators=[DataRequired(), Length(min=3, max=15,message="Value must contains between 3 and 15 numeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="Value must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])

    def validate_operatorId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Operator Name .")
    
    def validate_operatorParameterId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Operator Parameter.")


    class Meta:
        csrf = False

class SearchOperatorGrouping(FlaskForm):
    search_element = StringField('',validators=[Optional(), Length(min=3, max=75,message="Group Name Must contain between 3 and 75 characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message=" Group Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])

    class Meta:
        csrf = False

class AddSubParameterForm(FlaskForm):
    operatorParameterId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Parent Parameter is required")])
    operatorGroupingId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Operator Grouping is required")])
    displayName = StringField('', validators=[DataRequired(), Length(min=3, max=75,message="Display Name must contains between 3 and 75 characters"),Regexp(r"^[a-zA-Z0-9\s@#$()+_\-/]+$", message= "Display Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    parameterName = StringField('', validators=[DataRequired(), Length(min=3, max=75,message="Parameter Name must contains between 3 and 75 characters"),Regexp(r"^[a-zA-Z0-9\s@#$()+_\-/]+$", message= "Parameter Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    operatorId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Operator is required")])
    minLength = StringField('', validators=[DataRequired(), Length(min=1, max=10,message="Min Length must contains between 1 and 10 numeric characters"),Regexp(r"^\d+(\.\d+)?$", message= "Min Length must contain only numeric characters")])
    maxLength = StringField('', validators=[DataRequired(), Length(min=1, max=10,message="Max Length must contains between 1 and 10 numeric characters"),Regexp(r"^\d+(\.\d+)?$", message= "Max Length must contain only numeric characters")])
    sort = StringField('', validators=[Optional(), Length(min=1, max=10,message="Sort must contains between 1 and 10 numeric characters"),Regexp(r"^\d+(\.\d+)?$", message= "Sort must contain only numeric characters")])
    fieldType = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Field Type is required")])
    pattern = StringField('', validators=[Optional(), Length(min=1, max=75,message="Pattern must contains between 1 and 75 characters"),Regexp(r"^[a-zA-Z0-9\s@#$()+_\-/]+$", message= "Pattern must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    apiCode = StringField('', validators=[DataRequired(), Length(min=3, max=15,message="Api Code must contains between 3 and 15 characters"),Regexp(r"^[a-zA-Z0-9\s]+$", message= "Api Code contain only alphanumeric characters (letters, digits) and spaces.")])
    transactionAPIId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "TransactionAPI is required")])
    isActive = BooleanField('', validators=[Optional()])
    isMandatory = BooleanField('', validators=[Optional()])
    hasGrouping = BooleanField('', validators=[Optional()])
    hasIncludeApiCall= BooleanField('', validators=[Optional()])
    isReferenceKey = BooleanField('', validators=[Optional()])
    hasApiCall = BooleanField('', validators=[Optional()])
    apiCall = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Api Call is required")])

    def validate_operatorParameterId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Parent Parameter .")
    
    def validate_operatorGroupingId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Operator Grouping.")
        
    def validate_operatorId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Operator Name .")
    
    def validate_transactionAPIId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid TransactionAPI.")

    class Meta:
        csrf = False

class SearchSubParameter(FlaskForm):
    search_element = StringField('',validators=[Optional(), Length(min=3, max=75,message="Display Name Must contain between 3 and 75 characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message=" Display Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])

    class Meta:
        csrf = False

class AddSubParameterGrouping(FlaskForm):
    groupName = StringField('', validators=[DataRequired(), Length(min=3, max=75,message="Group Name must contains between 3 and 75 characters"),Regexp(ALPHANUMERIC_REGEX, message= "Group Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    operatorId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Operator is required")])
    subParameterId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Operator Sub Parameter is required")])
    value = StringField('', validators=[DataRequired(), Length(min=3, max=15,message="Value must contains between 3 and 15 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPECIAL_CHARACTERS, message= "Value contain only alphanumeric characters (letters, digits) and spaces.")])

    def validate_operatorId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Operator Name.")
    
    def validate_subParameterId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Sub Parameter Name.")


    class Meta:
        csrf = False


class SearchSubParameterGouping(FlaskForm):
    search_element = StringField('',validators=[Optional(), Length(min=3, max=75,message="Group Name Must contain between 3 and 75 characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message=" Group Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])

    class Meta:
        csrf = False


class AddTaxTypeForm(FlaskForm):
    taxTypeName = StringField("",validators=[DataRequired(),Length(min=3, max=75),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and these special characters are allowed: :@#$()+_-/.")])
    taxType = SelectField("",choices=[("PERCENTAGE", "PERCENTAGE"), ("FLAT", "FLAT")],validators=[DataRequired()])
    primaryTax = IntegerField("",validators=[DataRequired(),NumberRange(min=0, max=100, message="Value must be between 1 and 100")])
    secondaryTax = IntegerField("",validators=[DataRequired(),NumberRange(min=0, max=100, message="Value must be between 1 and 100")])
    class Meta:
        csrf = False

class AccountSummarySearchForm(FlaskForm):
    selectYear = SelectField('', choices=[],validate_choice=False, validators=[Optional()])
    selectMonth = SelectField("",choices=[("January", "January"),("February", "February"),("March", "March"),("April", "April"),("May", "May"),("June", "June"),("July", "July"),("August", "August"),("September", "September"),("October", "October"),("November", "November"),("December", "December")],validate_choice=False,validators=[Optional()])

    def validate_selectYear(self, field):
        current_year = datetime.datetime.now().year
        if str(field.data) != str(current_year) and str(field.data) != str(current_year-1):
            raise ValidationError("Invalid Year")

    class Meta:
        csrf = False


class SearchUserTypesList(FlaskForm):
    search_element = StringField('',validators=[Optional(), Length(min=3, max=75,message="Permission Name Name Must contain between 3 and 75 characters"),Regexp(ALPHANUMERIC_REGEX, message="Permission Name Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])

    class Meta:
        csrf = False

class SearchUserCommissionsList(FlaskForm):
    categoryId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    serviceId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    subServiceId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    profileId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    paymentGatewayId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
        
    def validate_categoryId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Categories.")
        categories_queryset = ServiceGrouping.objects(id=field.data,status__nin=[2]).first()
        if not categories_queryset:
            raise ValidationError("Please select a Valid Categories")
    
    def validate_serviceId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Services.")
        categories_queryset = Categories.objects(id=field.data,status__nin=[2]).first()
        if not categories_queryset:
            raise ValidationError("Please select a Valid Services")
    
    def validate_subServiceId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid SubServices.")
        services_queryset = Service.objects(id=field.data,status__nin=[2]).first()
        if not services_queryset:
            raise ValidationError("Please select a Valid SubServices")
    
    def validate_profileId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Profiles.")
        profiles_queryset = Patterns.objects(id=field.data,status__nin=[2]).first()
        if not profiles_queryset:
            raise ValidationError("Please select a Valid Profiles")
        
    def validate_paymentGatewayId(self,field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Payment Gateway.")
        apis_queryset = TransactionAPI.objects(id=field.data,status__nin=[2]).first()
        if not apis_queryset:
            raise ValidationError("Please select a Payment Gateway")
    class Meta:
        csrf = False


class AddCircleMasterForm(FlaskForm):
    name = StringField('',validators=[DataRequired(), Length(min=3, max=75,message="Circle Name must contain between 3 and 75 numeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="Circle Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    circleRefId = StringField('',validators=[DataRequired(), Length(min=1, max=15,message="Circle Ref Id must contain between 1 and 15 numeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="Circle Ref Id must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    paymentGatewayId = SelectField('',choices=[], validate_choice=False,validators=[DataRequired()])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)


    def validate_name(self, field):
        existing = Circles.objects(name=field.data, status__in=[0,1]).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Circles Name already exists.')
        
    class Meta:
        csrf = False

class SearchCircleMaster(FlaskForm):
    search_element = StringField('',validators=[Optional(), Length(min=3, max=75,message="Name Must contain between 3 and 75 characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message=" Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])

    class Meta:
        csrf = False


class AddPrepaidOperators(FlaskForm):
    name = StringField('',validators=[DataRequired(), Length(min=3, max=75,message="Please enter a Name between 3 and 75 numeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    operatorCode = StringField('',validators=[DataRequired(), Length(min=1, max=15,message="Please enter a Operator Code between 1 and 15 numeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="Operator Code must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])
    prepaidPgId = SelectField('',choices=[], validate_choice=False,validators=[DataRequired()])
    image = FileField('', validators=[Optional(),FileAllowed(['jpg', 'jpeg', 'png'], INVALID_Image_MESSAGE)])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)


    def validate_name(self, field):
        existing = PrepaidOperators.objects(name=field.data, status__in=[0,1]).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Name already exists.')
        
    class Meta:
        csrf = False

class SearchPrepaidOperatorsName(FlaskForm):
    search_element = StringField('',validators=[Optional(), Length(min=3, max=75,message="Name Must contain between 3 and 75 characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message=" Name must contain only alphanumeric characters, spaces, and specific special characters:@#$()+_-/.")])

    class Meta:
        csrf = False 

class VirtualAccountForm(FlaskForm):
    transactionAPIId = SelectField('', choices=[],validate_choice=False, validators=[DataRequired()])
    noOfAccounts = IntegerField('', validators=[
        DataRequired(),
        NumberRange(min=1, max=9999, message="noOfAccounts must contain only digits and be between 1 and 9999.")
    ])
    isThirdParty = BooleanField('')
    remark = StringField('', validators=[DataRequired(),Length(min=1,max=150),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])
    
   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_transactionAPIId(self, field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid transactionAPIId format.")
        transaction_API_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1]).order_by("-id")
        if not transaction_API_queryset:
            raise ValidationError("Selected TransactionAPI is not valid.")



class VirtualAccountSearchForm(FlaskForm):
    virtualAccountNumber = StringField('', validators=[
        Optional(),Length(min=MIN_LENGTH_3, max=35, message="Virtual Account length between 3 and 35 characters."),
        Regexp(r"^[a-zA-Z0-9]+$", message="Only alpha numeric are allowed without space.")
    ])
    
    selectStatus = SelectField('',
    choices=[
        ("", "Select status"),
        ("Active", "Active"),
        ("Deactive", "Deactive")
    ],validators=[
        Optional()
    ],
    coerce=str)

    class Meta:
        csrf = False

class AssignedVirtualAccountForm(FlaskForm):
    userId = SelectField('', choices=[],validate_choice=False, validators=[DataRequired()])
    virtualAccountId = SelectField('', choices=[],validate_choice=False, validators=[DataRequired()])
   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_userId(self, field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid userId format.")
        user_queryset = Users.objects(id=field.data,status__in=[0,1]).order_by("-id")
        if not user_queryset:
            raise ValidationError("Selected userId is not valid.")

    def validate_virtualAccountId(self, field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid virtualAccountId format.")
        va_queryset = VirtualAccounts.objects(id=field.data,status__in=[0,1]).order_by("-id")
        if not va_queryset:
            raise ValidationError("Selected virtualAccountId is not valid.")

class AssignedVirtualAccountFormSearch(FlaskForm):
    userId = SelectField('', choices=[], validate_choice=False)  # optional
    virtualAccountId = SelectField('', choices=[], validate_choice=False)  # optional
  
    def validate_userId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid userId format. Please select a valid userId.")
        
            users_queryset = Users.objects(id=field.data,status__in=[0,1]).first()
            if not users_queryset:
                raise ValidationError("Selected userId is not valid.")

    def validate_virtualAccountId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid virtualAccountId format. Please select a valid virtualAccountId.")
        
            vaaccounts_queryset = VirtualAccounts.objects(id=field.data,status__in=[0,1]).first()
            if not vaaccounts_queryset:
                raise ValidationError("Selected virtualAccountId is not valid.")

    class Meta:
        csrf = False
        


class AssignedThirdPartyVirtualAccountForm(FlaskForm):
    userId = SelectField('', choices=[],validate_choice=False, validators=[DataRequired()])
    virtualAccountId = SelectField('', choices=[],validate_choice=False, validators=[DataRequired()])
   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_userId(self, field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid userId format.")
        user_queryset = ThirdPartyMerchants.objects(id=field.data,status__in=[0,1]).order_by("-id")
        if not user_queryset:
            raise ValidationError("Selected userId is not valid.")

    def validate_virtualAccountId(self, field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid virtualAccountId format.")
        va_queryset = VirtualAccounts.objects(id=field.data,status__in=[0,1]).order_by("-id")
        if not va_queryset:
            raise ValidationError("Selected virtualAccountId is not valid.")

class AssignedThirdPartyVirtualAccountFormSearch(FlaskForm):
    thirdpartyUserId = SelectField('', choices=[], validate_choice=False)  # optional
    virtualAccountId = SelectField('', choices=[], validate_choice=False)  # optional

    def validate_thirdpartyUserId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid thirdpartyUserId format. Please select a valid thirdpartyUserId.")
        
            users_queryset = ThirdPartyMerchants.objects(id=field.data,status__in=[0,1]).first()
            if not users_queryset:
                raise ValidationError("Selected thirdpartyUserId is not valid.")

    def validate_virtualAccountId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid virtualAccountId format. Please select a valid virtualAccountId.")
        
            vaaccounts_queryset = VirtualAccounts.objects(id=field.data,status__in=[0,1]).first()
            if not vaaccounts_queryset:
                raise ValidationError("Selected virtualAccountId is not valid.")
            
    class Meta:
        csrf = False




class WhiteListSearchForm(FlaskForm):
    search_element = StringField('', validators=[
        Optional(),
        Length(min=3, max=75, message="Search input must be between 3 and 75 characters."),
        Regexp(ALPHANUMERIC_REGEX, message="Search input must be between 3 and 75 characters and can include only alphanumeric and special characters @#$()+_-/.")
    ])


class WhiteListAccountHistorySearchForm(FlaskForm):
    search_element = StringField('', validators=[
        Optional(),
        Length(min=3, max=75, message="Search input must be between 3 and 75 characters."),
        Regexp(ALPHANUMERIC_REGEX, message="Search input must be between 3 and 75 characters and can include only alphanumeric and special characters @#$()+_-/.")
    ])

class AutoCollectTransactionSearchForm(FlaskForm):
    search_element = StringField('', validators=[
        Optional(),
        Regexp(r"^[a-zA-Z0-9\s]+$", message="Virtual Account must be between 10 and 35 characters and can include only alphanumeric characters")
    ])






# class ProfileForm(FlaskForm):
#     name = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])
#     rank = IntegerField('', validators=[DataRequired(),Regexp(r"^[1-9][0-9]{0,5}$", message="Rank must be a number between 1 and 999999")])
#     description = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_1, max=MAX_LENGTH_150),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])
#     code = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_1, max=MAX_LENGTH_15),Regexp(ALPHANUMERIC_WITHOUT_SPECIAL_CHARACTERS, message="Code can only contain letters, numbers, and spaces.")])
#     userPermissionId = SelectField('', choices=[],validate_choice=False, validators=[DataRequired()])
#     payinPaymentGatewaysList = SelectMultipleField('', choices=[],validate_choice=False, validators=[DataRequired()])
#     defaultProfile = BooleanField('')
#     payinEnable = BooleanField('')
#     defaultPayinPaymentGatewayId = SelectField('', choices=[],validate_choice=False, validators=[Optional()])
#     payoutEnable = BooleanField('')
#     defaultPayoutPaymentGatewayId = SelectField('', choices=[],validate_choice=False, validators=[Optional()])
#     remark = StringField('', validators=[Length(min=1,max=150),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])
#     payoutPaymentGatewayId=SelectField('', choices=[],validate_choice=False, validators=[Optional()])

#     def __init__(self, *args, current_id=None, **kwargs):
#         super().__init__(*args, **kwargs)
#         self.current_id = str(current_id) if current_id else None
#         if self.current_id:
#             self.remark.validators.append(DataRequired())  # Make remark mandatory
#         if self.payinEnable==True:
#             # self.defaultPayinPaymentGatewayId.validators.append(DataRequired())
#             self.defaultPayinPaymentGatewayId.validators = [
#                 v for v in self.defaultPayinPaymentGatewayId.validators if not isinstance(v, Optional)
#             ]
#             self.defaultPayinPaymentGatewayId.validators.append(DataRequired())
#         if self.payoutEnable==True:
#             # self.defaultPayoutPaymentGatewayId.validators.append(DataRequired())
           
#             if self.current_id:
#                 self.payoutPaymentGatewayId.validators = [
#                     v for v in self.payoutPaymentGatewayId.validators if not isinstance(v, Optional)
#                 ]
#                 self.payoutPaymentGatewayId.validators.append(DataRequired())
#             else:
#                 self.defaultPayoutPaymentGatewayId.validators = [
#                 v for v in self.defaultPayoutPaymentGatewayId.validators if not isinstance(v, Optional)
#                 ]
#                 self.defaultPayoutPaymentGatewayId.validators.append(DataRequired())
            

#         if not self.current_id:
#             del self.remark
#         # self.process(*args, **kwargs)

#     def validate_defaultPayinPaymentGatewayId(self, field):
#         if self.payinEnable.data:
#             if not field.data:
#                 raise ValidationError("Please select a Payin Payment Gateway.")
#             pg = TransactionAPI.objects(id=field.data, transactionType="PaymentGateway", status__in=[0,1]).first()
#             if not pg:
#                 raise ValidationError("Please select a valid Payin Payment Gateway.")

#     def validate_defaultPayoutPaymentGatewayId(self, field):
#         if not self.current_id and self.payoutEnable.data:
#             if not field.data:
#                 raise ValidationError("Please select a Payout Payment Gateway.")
#             pg = TransactionAPI.objects(id=field.data, transactionType="Payout",status__in=[0,1]).first()
#             if not pg:
#                 raise ValidationError("Please select a valid Payout Payment Gateway.")

#     def validate_payoutPaymentGatewayId(self, field):
#         if self.current_id and self.payoutEnable.data:
#             if not field.data:
#                 raise ValidationError("Please select a Payout Payment Gateway.")
#             pg = TransactionAPI.objects(id=field.data, transactionType="Payout", status__in=[0,1]).first()
#             if not pg:
#                 raise ValidationError("Please select a valid Payout Payment Gateway.")
#     def validate_payinPaymentGatewaysList(self,field):
#         valid_count = TransactionAPI.objects(id__in=field.data,transactionType= "PaymentGateway",status__in=[0,1]).count()
#         if valid_count != len(field.data):
#             raise ValidationError("One or more selected APIs are invalid.")

                
class UpdateStatusRemarkForm(FlaskForm):
    remark = StringField('', validators=[DataRequired(),Length(min=1, max=100),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])



    
class PayoutSearchForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    selectStatus = SelectField('', choices=[
        "All","Success","Processing","Failed","Reversal","Refund"
        ],validators=[Optional()])
    transactionType = SelectField('', choices=[
        ("All","All"),
        ("Credit","Credit"),
        ("Debit","Debit")
        ],validators=[Optional()])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="SearchId accepts only AlphaNumeric Characters")])
    pgId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    siteTitle = SelectField('', choices=[],validate_choice=False,validators=[Optional()])

    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
            
    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="Payout").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid PG Id.")
            
    def validate_siteTitle(self, field):
        if field.data:
            mulappsites_queryset = MultipleAppSites.objects(siteCode=field.data,status__in=[0,1]).first()
            if not mulappsites_queryset:
                raise ValidationError("Please select a valid Site Title.")
            
    def validate_stateId(self, field):
        
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid State Id.")
            states_queryset = States.objects(id=field.data,status__in=[0,1]).first()
            if not states_queryset:
                raise ValidationError("Please select a valid State Id.")

    class Meta:
        csrf = False

class PayoutSuccessSearchForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    pgId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="SearchId accepts only AlphaNumeric Characters")])
    siteTitle = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    transactionType = SelectField('', choices=[
        ("All","All"),
        ("Credit","Credit"),
        ("Debit","Debit")
        ],validators=[Optional()])
    
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")

    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="Payout").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid PG Id.")
                
    def validate_siteTitle(self, field):
        if field.data:
            mulappsites_queryset = MultipleAppSites.objects(siteCode=field.data,status__in=[0,1]).first()
            if not mulappsites_queryset:
                raise ValidationError("Please select a valid Site Title.")
            
    class Meta:
        csrf = False

class PayoutPendingSearchForm(FlaskForm):
    startDate = StringField('',validators=[
        Optional(),
        Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[
        Optional(),
        Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="SearchId accepts only AlphaNumeric Characters")])
    siteTitle = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    selectStatus = SelectField('', choices=[
        ("All","Credit"),
        ("Processing","Processing"),
        ("Failed","Failed"),
        ],validators=[Optional()])

    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
          
    def validate_siteTitle(self, field):
        if field.data:
            mulappsites_queryset = MultipleAppSites.objects(siteCode=field.data,status__in=[0,1]).first()
            if not mulappsites_queryset:
                raise ValidationError("Please select a valid Site Title.")
            
    class Meta:
        csrf = False

class BankPendingPayoutTransactions(FlaskForm):
    startDate = StringField('',validators=[Optional(),Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_32,message="OrderId Must be between 3 and 32 characters"),Regexp(ALPHANUMERIC_REGEX, message="OrderId accepts only AlphaNumeric Characters")])
    selectStatus = SelectField('', choices=["All","Processing","Failed"],validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False , validators=[Optional()])

    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchants_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchants_queryset:
                raise ValidationError("Please select a Valid Merchant Id")

    class Meta:
        csrf = False

class BeneficiaryListForm(FlaskForm):
    class Meta:
        csrf = False
    creditorAccountNumber = StringField('', validators=[
        Optional(),
        Length(min=9, max=20, message="Account Number must be between 9 and 20 digits."),
        Regexp(ACCOUNT_NUMBER_REGEX, message="Account Number must be numeric and contain 9 to 20 digits only.")
    ])

    searchId = StringField('', validators=[
        Optional(),
        Length(min=3, max=75, message="Search Name must be between 3 and 75 characters."),
        Regexp(ALPHANUMERIC_REGEX, message="Search Name must contain only alphanumeric and @#$()+_-/ characters.")
    ])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchants_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchants_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
   

class AutoBenficiaryListForm(FlaskForm):
    transactionAPIId  = SelectField('', choices=[],validate_choice=False,validators=[DataRequired( message="Please select a payment gateway.")])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None

    def validate_transactionAPIId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid transactionAPI Id.")
            transactionAPIId_queryset = TransactionAPI.objects(id=field.data,status__nin=[2]).first()
            if not transactionAPIId_queryset:
                raise ValidationError("Please select a Valid transactionAPI Id")
            
            existing = AutoBeneficiaries.objects(transactionAPIId=field.data).first()
            if existing and str(existing.id) != self.current_id:
                raise ValidationError('Payment gateway already exists')


            
    class Meta:
        csrf = False

class PayinSearchForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    selectStatus = SelectField('', choices=[ "All","Success","Processing","Failed","Refund" ],validators=[Optional()])
    transactionType = SelectField('', choices=[ ("All","All"),("Credit","Credit"), ("Debit","Debit") ],validators=[Optional()])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="SearchId accepts only AlphaNumeric Characters")])
    pgId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    paymentModeId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    subPaymentModeId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    siteTitle = SelectField('', choices=[],validate_choice=False,validators=[Optional()])

    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
            
    def validate_paymentModeId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Payment Id.")
            payment_mode_queryset = PaymentMode.objects(id=field.data,status__nin=[2]).first()
            if not payment_mode_queryset:
                raise ValidationError("Please select a Valid Payment Id")
            
    def validate_subPaymentModeId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid SubPayment Mode Id.")
            sub_payment_mode_queryset = SubPaymentModes.objects(id=field.data,status__nin=[2]).first()
            if not sub_payment_mode_queryset:
                raise ValidationError("Please select a Valid Sub PaymentMode Id")
            
    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="PaymentGateway").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid PG Id.")
            
    def validate_siteTitle(self, field):
        if field.data:
            mulappsites_queryset = MultipleAppSites.objects(siteCode=field.data,status__in=[0,1]).first()
            if not mulappsites_queryset:
                raise ValidationError("Please select a valid Site Title.")
            
    def validate_stateId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid State Id.")
            states_queryset = States.objects(id=field.data,status__in=[0,1]).first()
            if not states_queryset:
                raise ValidationError("Please select a valid State Id.")

    class Meta:
        csrf = False

class PayinSuccessSearchForm(FlaskForm):
    startDate = StringField('',validators=[Optional(),Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="SearchId accepts only AlphaNumeric Characters")])
    siteTitle = SelectField('', choices=[],validate_choice=False,validators=[Optional()])

    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
          
    def validate_siteTitle(self, field):
        if field.data:
            mulappsites_queryset = MultipleAppSites.objects(siteCode=field.data,status__in=[0,1]).first()
            if not mulappsites_queryset:
                raise ValidationError("Please select a valid Site Title.")
            
    class Meta:
        csrf = False

class PrepaidMobileSetupForm(FlaskForm):
    enablePrepaid = BooleanField("Enable Prepaid")  
    prepaidPgId = SelectField("Prepaid PG",choices=[],validate_choice=False, validators=[Optional()])
    prepaidProviderId = SelectField("Prepaid Provider Api",choices=[],validate_choice=False, validators=[Optional()])
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        if self.enablePrepaid.data==True:
          
            # self.prepaidPgId.validators = [
            #     v for v in self.prepaidPgId.validators if not isinstance(v, Optional)
            # ]
            # self.prepaidPgId.validators.append(DataRequired())
            self.prepaidProviderId.validators = [
                v for v in self.prepaidProviderId.validators if not isinstance(v, Optional)
            ]
            self.prepaidProviderId.validators.append(DataRequired())
                   
    def validate_prepaidProviderId(self, field):
        if not field.data:
            raise ValidationError("plaesae   select provider ")
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid PG ID format.")
            prepaid_apis_queryset = TransactionAPI.objects(id=field.data,status__nin=[2]).first()
            if not prepaid_apis_queryset:
                raise ValidationError("Selected Prepaid Provider is invalid.")

class PayinSettlementReportsForm(FlaskForm):
    startDate = StringField('',validators=[Optional(),Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    orderId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_32,message="OrderId Must be between 3 and 32 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="OrderId accepts only AlphaNumeric Characters")])
    merchantId = SelectField('', choices=[],validate_choice=False , validators=[Optional()])

    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchants_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchants_queryset:
                raise ValidationError("Please select a Valid Merchant Id")

    class Meta:
        csrf = False


class WalletCreditDebitForm(FlaskForm):
    patternId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Pattern is required")])
    userId = SelectField('',choices=[], validate_choice=False,validators=[DataRequired(message = "User Name is required")])
    credittransferType = SelectField('', choices=[('Credit', 'Credit'), ('Debit', 'Debit'),('Debit', 'Debit')], validators=[Optional()])
    amount = StringField('',validators=[DataRequired(), Length(min=1, max=10,message="Settlement Amount must contains between 1 and 10 numeric characters"),Regexp(r'^\d+(\.\d+)*$', message="Settlement Amount contains only numeric characters")])
    comment = StringField('', validators=[DataRequired(),Length(min=1, max=100,message="Remark must be between 1 and 100 characters."),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/.")])
    
    def validate_patternId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Pattern Id.")
            pattern_queryset = Patterns.objects(id=field.data,status__nin=[2]).first()
            if not pattern_queryset:
                raise ValidationError("Please select a Valid Pattern Id")
    
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
            
class AdminOverallBalancesReportsForm(FlaskForm):
    startDate = StringField('',validators=[Optional(),Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    transferType = SelectField('', choices=[('Payin', 'Payin'), ('Payout', 'Payout')], validators=[Optional()])
    walletType = SelectField('', choices=[('Credit', 'Credit'), ('Debit', 'Debit')], validators=[Optional()])

    class Meta:
        csrf = False

class CommissionSettleSearchForm(FlaskForm):
    selectYear = SelectField('', choices=[],validate_choice=False, validators=[Optional()])
    selectMonth = SelectField("",choices=[("January", "January"),("February", "February"),("March", "March"),("April", "April"),("May", "May"),("June", "June"),("July", "July"),("August", "August"),("September", "September"),("October", "October"),("November", "November"),("December", "December")],validate_choice=False,validators=[Optional()])

    def validate_selectYear(self, field):
        current_year = datetime.datetime.now().year
        if str(field.data) != str(current_year) and str(field.data) != str(current_year-1):
            raise ValidationError("Invalid Year")

    class Meta:
        csrf = False

class CommissionTdsSetupForm(FlaskForm):
    tdsLimitAmount = StringField('', validators=[DataRequired(message='TDS Limit is required'),Regexp(DECIMALPOINT_REGEX, message='TDS Limit must contain only numbers and a decimal point (optional)') ])
    
    tdsChargePer = StringField('',validators=[DataRequired(message='TDS Charge is required'),Regexp(DECIMALPOINT_REGEX, message='TDS Charge must contain only numbers and a decimal point (optional)') ])

def validate_type(form,field):
    if field.data not in ('Amount', 'Percentage'):
        raise ValidationError("Please select either 'Amount' or 'Percentage'.")

class AddPGSettlementsForm(FlaskForm):
    transactionAPIId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message="Transaction Api is required")])
    settlementAmount = StringField('',validators=[DataRequired(), Length(min=1, max=10,message="Settlement Amount must contains between 1 and 10 numeric characters"),Regexp(r'^\d+(\.\d+)*$', message="Settlement Amount contains only numeric characters")])
    additionalChargeType = SelectField('', choices=[('Amount', 'Amount'),('Percentage', 'Percentage')],validate_choice=False,validators=[DataRequired(),validate_type])
    additionalChargeValue = StringField('',validators=[DataRequired(), Length(min=1, max=10,message="additionalChargeValue must contains between 1 and 10 numeric characters"),Regexp(r'^\d+(\.\d+)*$', message="additionalChargeValue contains only numeric characters")])
    gstChargeType = SelectField('', choices=[('Amount', 'Amount'),('Percentage', 'Percentage')],validate_choice=False,validators=[DataRequired(),validate_type])
    gstChargeValue = StringField('',validators=[DataRequired(), Length(min=1, max=10,message="gstChargeValue must contains between 1 and 10 numeric characters"),Regexp(r'^\d+(\.\d+)*$', message="gstChargeValue contains only numeric characters")])
    settlementDateTime = DateTimeLocalField('',format='%Y-%m-%dT%H:%M', validators=[DataRequired(message="settlementDateTime is required")])

    class Meta:
        csrf = False

class TransactionLimitSettingForm(FlaskForm):
    name = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    code = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_15,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    pgType = StringField('', validators=[DataRequired(), Length(min=5, max=MAX_LENGTH_10,message=INVALID_LENGTH_MESSAGE),Regexp(ALPHANUMERIC_REGEX, message=INVALID_FORMAT_MESSAGE)])
    singleTxnLowerLimit = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MIN_LENGTH_10,message=INVALID_LENGTH_MESSAGE),Regexp(ONLY_NUMERIC, message=INVALID_FORMAT_MESSAGE)])
    singleTxnUpperLimit = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MIN_LENGTH_10,message=INVALID_LENGTH_MESSAGE),Regexp(ONLY_NUMERIC, message=INVALID_FORMAT_MESSAGE)])
    dailyTxnLimit = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MIN_LENGTH_10,message=INVALID_LENGTH_MESSAGE),Regexp(ONLY_NUMERIC, message=INVALID_FORMAT_MESSAGE)])
    dailyTxnCount = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MIN_LENGTH_10,message=INVALID_LENGTH_MESSAGE),Regexp(ONLY_NUMERIC, message=INVALID_FORMAT_MESSAGE)])
    minimunAccountBalance = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MIN_LENGTH_10,message=INVALID_LENGTH_MESSAGE),Regexp(ONLY_NUMERIC, message=INVALID_FORMAT_MESSAGE)])
    monthlyTxnLimit = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MIN_LENGTH_10,message=INVALID_LENGTH_MESSAGE),Regexp(ONLY_NUMERIC, message=INVALID_FORMAT_MESSAGE)])
    monthlyTxnCount = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MIN_LENGTH_10,message=INVALID_LENGTH_MESSAGE),Regexp(ONLY_NUMERIC, message=INVALID_FORMAT_MESSAGE)])
    isUserWise = StringField('', validators=[Optional()])
    paymentGatewayIds = SelectMultipleField('', choices=[],validate_choice=False, validators=[DataRequired()])
    userIds = SelectMultipleField('', choices=[],validate_choice=False, validators=[Optional()])
    paymentMode = SelectMultipleField('', choices=[],validate_choice=False, validators=[Optional()])
    subPaymentMode = SelectMultipleField('', choices=[],validate_choice=False, validators=[Optional()])
    transactionAmountLimit = SelectMultipleField('', choices=[],validate_choice=False, validators=[Optional()])
    transactionCountLimit = SelectMultipleField('', choices=[],validate_choice=False, validators=[Optional()])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        if self.isUserWise.data == "True":
            self.userIds.validators = [v for v in self.userIds.validators if not isinstance(v, Optional)]
            self.userIds.validators.append(DataRequired())
        # self.process(*args, **kwargs)

    def validate_name(self, field):
        existing = TransactionLimitSettings.objects(name=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Name already exists.')
        
    def validate_isUserWise(self, field):
        if field.data not in ("True", "none", None, ""):
            raise ValidationError("Value must be 'True' or 'none'.")
    
    def validate_userIds(self,field):
        if not field.data:
            raise ValidationError("Please select User Name")
        if field.data:
            for each_userid in field.data:
                if not ObjectId.is_valid(each_userid):
                    raise ValidationError("Invalid User ID format.")
                
        user_queryset = Users.objects(id__in=field.data,status__nin=[2]).first()
        if not user_queryset:
            raise ValidationError("Selected User ID is invalid.")    

class AddCompanyDetailsForm(FlaskForm):
    transactionApiIdsList = SelectMultipleField('', choices=[],validate_choice=False, validators=[DataRequired(message="Payin is required")])
    invoiceTemplate = StringField('',validators=[Optional()])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_transactionApiIdsList(self, field):
        valid_count = TransactionAPI.objects(id__in=field.data,status__in=[0,1]).count()
        if valid_count != len(field.data):
            raise ValidationError("One or more selected APIs are invalid.")
    
    class Meta:
        csrf = False

class UtilityTransactionReport(FlaskForm):
    startDate = StringField('',validators=[Optional(),Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    merchantId = SelectField('', choices=[],validate_choice=False , validators=[Optional()])
    selectStatus = SelectField('', choices=["All","Success","Processing","Failed"],validators=[Optional()])
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchants_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchants_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
    class Meta:
        csrf = False

class DownlineListSearchForm(FlaskForm):
    startDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Start Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="End Date must be in DD-MM-YYYY format")])
    merchantType = SelectField('', choices=[ ("Select","Select"), ("Super Distributor","Super Distributor"), ("Master Distributor","Master Distributor"), ("Area Distributor","Area Distributor"), ("Retailer","Retailer")],validators=[Optional()])

    class Meta:
        csrf = False

class BalancePayoutReportsSearchForm(FlaskForm):      
    payout_selectedDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    payout_merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    payout_merchantType = SelectField('', choices=[
        ("",""),
        ("Super Distributor","Super Distributor"),
        ("Master Distributor","Master Distributor"),
        ("Area Distributor","Area Distributor"),
        ("Retailer","Retailer"),
        ("customer","customer")
        ],validators=[Optional()])

    def validate_payout_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
    class Meta:
        csrf = False  
  
class CummulativeReportsForm(FlaskForm):
    startDate = StringField('',validators=[Optional(),Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])

    class Meta:
        csrf = False

class OprationIncomeReportsForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp(r"^\d{2}-\d{2}-\d{4}( \d{2}:\d{2})?$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}( \d{2}:\d{2})?$", message="Date must be in DD-MM-YYYY format")])
    class Meta:
        csrf = False

class ReconciliationSearchForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")

    class Meta:
        csrf = False

class AdminGeneratedReportsForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    walletType = SelectField('', choices=[ ("", "Select"), ("payin", "payin"), ("payout", "payout") ],validators=[ Optional() ], coerce=str)
    reportType = SelectField('', choices=[ ("", "Select"), ("ledger", "ledger"), ("transactions", "transactions") ],validators=[ Optional() ], coerce=str)
                   
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")


class ChargeBackReportsForm(FlaskForm):
    startDate = StringField('',validators=[Optional(),Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    rrn = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="SearchId accepts only AlphaNumeric Characters")])
    merchantId = SelectField('', choices=[],validate_choice=False , validators=[Optional()])

    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")

    class Meta:
        csrf = False

class DownloadPayoutReportsForm(FlaskForm):
    startDate = StringField('',validators=[Optional(),Regexp(r"^\d{2}-\d{2}-\d{4}$", message="Start date must be in DD-MM-YYYY format")])
    endDate = StringField('',validators=[Optional(),Regexp(r"^\d{2}-\d{2}-\d{4}$", message="End date must be in DD-MM-YYYY format")])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
    class Meta:
        csrf = False

class GstTdsReportSearchForm(FlaskForm):
    selectYear = SelectField('', choices=[],validate_choice=False, validators=[Optional()])
    selectMonth = SelectField("",choices=[("January", "January"),("February", "February"),("March", "March"),("April", "April"),("May", "May"),("June", "June"),("July", "July"),("August", "August"),("September", "September"),("October", "October"),("November", "November"),("December", "December")],validate_choice=False,validators=[Optional()])
    userId = SelectField('', choices=[],validate_choice=False, validators=[Optional()])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_userId(self, field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid userId format.")
        user_queryset = Users.objects(id=field.data,status=1).order_by("-id")
        if not user_queryset:
            raise ValidationError("Selected userId is not valid.")

    def validate_selectYear(self, field):
        current_year = datetime.datetime.now().year
        if str(field.data) != str(current_year) and str(field.data) != str(current_year-1):
            raise ValidationError("Invalid Year")
        
class CommissionSearchForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")

    class Meta:
        csrf = False

class ReportsDownloadInvoices(FlaskForm):
    walletType = SelectField('', choices=[('', 'Select Wallet Type'),('payin', 'Pay In'), 
                                 ('payout', 'Pay Out')],validate_choice=True , validators=[DataRequired(message="Wallet Type is required")])
    option = RadioField('', 
                        choices=[('all', 'All'), 
                                 ('partial', 'Partial')],
                        validators=[InputRequired()])
    startDate = StringField('',validators=[Optional(),Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = TextAreaField('', validators=[])
    pgId = SelectField('', choices=[],validate_choice=False , validators=[DataRequired(message="PG is required")])

            
    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid PG")

    class Meta:
        csrf = False

class PayoutLedgerSearchForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="SearchId accepts only AlphaNumeric Characters")])
    pgId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])

    transactionType = SelectField('', choices=[
        ("All","All"),
        ("Credit","Credit"),
        ("Debit","Debit")
        ],validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    siteTitle = SelectField('', choices=[],validate_choice=False,validators=[Optional()])

    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")

    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="Payout").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid PG Id.")
            
    def validate_siteTitle(self, field):
        if field.data:
            mulappsites_queryset = MultipleAppSites.objects(siteCode=field.data,status__in=[0,1]).first()
            if not mulappsites_queryset:
                raise ValidationError("Please select a valid Site Title.")
    class Meta:
        csrf = False
       
class PayinLedgerSearchForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="SearchId accepts only AlphaNumeric Characters")])
    pgId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    siteTitle = SelectField('', choices=[],validate_choice=False,validators=[Optional()])

    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
            
    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="PaymentGateway").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid PG Id.")
            
    def validate_siteTitle(self, field):
        if field.data:
            mulappsites_queryset = MultipleAppSites.objects(siteCode=field.data,status__in=[0,1]).first()
            if not mulappsites_queryset:
                raise ValidationError("Please select a valid Site Title.")
            
    class Meta:
        csrf = False


class ApiManagementForm(FlaskForm):
    apiName = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])
    code=StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_1, max=MAX_LENGTH_15),Regexp(ALPHANUMERIC_REGEX, message="Code can only contain letters, numbers, and spaces.")])
    subCode=StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_1, max=MAX_LENGTH_15),Regexp(ALPHANUMERIC_WITHOUT_SPECIAL_CHARACTERS, message="Code can only contain letters, numbers, and spaces.")])
    perdayTransactionLimit= StringField('', validators=[Optional(), Length(min=0, max=MIN_LENGTH_10,message=INVALID_LENGTH_MESSAGE),Regexp(ONLY_NUMERIC, message=INVALID_FORMAT_MESSAGE)])
    invoiceType  = SelectField('', choices=[('Commission', 'Commission'),('Amount', 'Amount')],validate_choice=True,validators=[DataRequired()])
    transactionType =  SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    virtualCode = StringField('', validators=[Length(min=MIN_LENGTH_1, max=MAX_LENGTH_10),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="Code can only contain letters and numbers")])
    lastSixDigits= StringField('', validators=[Length(min=6, max=6,message="Escro Account Number must be 6 digits.")])
    ifscCode = StringField('', validators=[ Length(min=MIN_LENGTH_11, max=MIN_LENGTH_11,message="Please enter an IFSC of 11 characters"),Regexp(IFSC_REGEX, message="IFSC code must be 11 characters long and follow the format: 4 letters, followed by 0, then 6 digits")])
    preAuthorization=SelectField('',choices=[("", "Select status"),('True', 'True'),('False', 'False')],validate_choice=True, validators=[Optional()],coerce=str)
    autoSettlement=SelectField('',choices=[("", "Select status"),('True', 'True'),('False', 'False')],validate_choice=True, validators=[Optional()],coerce=str)
    settlementLimit=StringField('', validators=[Optional(), Length(min=0, max=MIN_LENGTH_10,message=INVALID_LENGTH_MESSAGE),Regexp(ONLY_NUMERIC, message=INVALID_FORMAT_MESSAGE)])
    cardBinEnable=SelectField('',choices=[("", "Select"),('True', 'True'),('False', 'False')],validate_choice=True, validators=[Optional()],coerce=str)
    isSeamless=SelectField('',choices=[("", "Select"),('True', 'True'),('False', 'False')],validate_choice=True,validators=[Optional()],coerce=str)
    priceType=SelectField('',choices=[("", "Select"),('common', 'common'),('variable', 'variable')],validate_choice=True,validators=[Optional()],coerce=str)
    inputKeyField=StringField('Enter Param Key', validators=[Optional()])
    inputValueField=StringField('Enter Param Key', validators=[Optional()])

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.transactionType.data == "Payout":
            self.virtualCode.validators.append(DataRequired())
            self.lastSixDigits.validators.append(DataRequired())
            self.ifscCode.validators.append(DataRequired())
        else:
            del self.virtualCode
            del self.lastSixDigits
            del self.ifscCode

class ApiMasterFormSearch(FlaskForm):
    search_element = StringField('',validators=[Optional(),
        Length(min=MIN_LENGTH_3,max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE),
        Regexp(ALPHANUMERIC_REGEX, message="Search field must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    class Meta:
        csrf = False  


class AssignKycListForm(FlaskForm):
    kycApiId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    documentNameList = SelectMultipleField(
        'Document Name*',
        choices=[
            ('Aadhar', 'Aadhar'),
            ('IndividualPan', 'Individual Pan'),
            ('Bank', 'Bank'),
            ('VideoKyc', 'Video KYC'),
            ('NameMatch', 'Name Match'),
            ('AadharMobileMatch', 'Aadhar Mobile Match')
        ],
        validators=[DataRequired(message="Please select at least one document name.")]
    )

    def validate_kycApiId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid kycApiId format.")
            kyc_apis_queryset = kycApis.objects(id=field.data,status__in=[0,1]).order_by("-id")
            if not kyc_apis_queryset:
                raise ValidationError("Selected KYC ApiId is not valid.")


class AssignKycFormSearch(FlaskForm):
    search_element_assign_kyc = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="Api Name must be 3 to 75 characters long"),
      Regexp(ALPHANUMERIC_REGEX, message="Api Name can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")
    ])
    
    class Meta:
        csrf = False


class KycApisForm(FlaskForm):
    apiName = StringField("API Name",validators=[DataRequired(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="Api Name must be 3 to 75 characters long"),Regexp(ALPHANUMERIC_REGEX,
                message="API Name must contain only alphanumeric characters, spaces, and specific special characters: @#$()+_-/")])
    code = SelectField(
        "Code",
        choices=[
            ("", "Select Code"),
            ("Signzy", "Signzy"),
            ("Setu", "Setu"),
            ("Vayana", "Vayana")
        ],validators=[DataRequired(message="Code is required.")])
    inputKeyField=StringField('Enter Param Key', validators=[Optional()])
    inputValueField=StringField('Enter Param Key', validators=[Optional()])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_apiName(self, field):
        existing = kycApis.objects(apiName=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Api Name already exists.')


class KycApiFormSearch(FlaskForm):
    search_element = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="Api Name must be 3 to 75 characters long"),
        Regexp(ALPHANUMERIC_REGEX, message="Api Name can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")
    ])
    
    class Meta:
        csrf = False


class KycApiChargeFormSearch(FlaskForm):
    kycApiId = SelectField('', choices=[], validate_choice=False) 

    def validate_kycApiId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid kycApiId Id.")
            kyc_apis_queryset = kycApis.objects(id=field.data,status__in=[0,1]).first()
            if not kyc_apis_queryset:
                raise ValidationError("Please select a Valid kycApiId")
    
    class Meta:
        csrf = False
        
class smsSearchForm(FlaskForm):
    search_element = StringField('',validators=[Optional(),
            Length(min=MIN_LENGTH_3,max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE),
            Regexp(ALPHANUMERIC_REGEX, message="Search field must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    class Meta:
        csrf = False

class assignSmsSearchForm(FlaskForm):
    assign_search_element = StringField('',validators=[Optional(),
            Length(min=MIN_LENGTH_3,max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE),
            Regexp(ALPHANUMERIC_REGEX, message="Search field must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    class Meta:
        csrf = False

class smsTemplateSearchForm(FlaskForm):
    smstemplate_search_element = StringField('',validators=[Optional(),
            Length(min=MIN_LENGTH_3,max=MAX_LENGTH_75, message=INVALID_LENGTH_MESSAGE),
            Regexp(ALPHANUMERIC_REGEX, message="Search field must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    class Meta:
        csrf = False

class AddSmsForm(FlaskForm):
    apiName = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])
    code = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
    
    def validate_apiName(self, field):     
        existing = smsApis.objects(apiName=field.data, status__in=[0,1]).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Api Name already exists!')

class AddAssignSmsForm(FlaskForm):
    smsApiId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    otpTypeList = SelectMultipleField('', choices=[],validate_choice=False, validators=[DataRequired()])

class addSmsTemplateForm(FlaskForm):
    smsApiId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    otpTypeList = SelectField('', choices=[],validate_choice=False, validators=[DataRequired()])
    templateContent = StringField('', validators=[DataRequired(),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/")])

class ApIDocumentationGuideForm(FlaskForm):
    title = StringField('', validators=[
        DataRequired(message="Title is Required"),
        Length(min=MIN_LENGTH_1, max=MAX_LENGTH_150,message ="Title length must be in 1 to 150 only"),Regexp(ALPHANUMERIC_REGEX,message="Title must contain Only alphanumeric characters and @#$()+_-/ allowed")
        
    ])
    description = StringField('', validators=[
        DataRequired(message="Description is Required"),
        Length(min=MIN_LENGTH_1, max=MAX_LENGTH_150,message = "Description length must be in 1 to 150 only"),Regexp(ALPHANUMERIC_REGEX,message="Description must contain Only alphanumeric characters and @#$()+_-/ allowed")
        
    ])
    priority = StringField('', validators=[
        DataRequired(message="Priority is Required"),
        Length(min=MIN_LENGTH_1, max=MAX_LENGTH_10,message = "Priority length must be in 1 to 10 digits only"),Regexp(ONLY_NUMERIC,message="Priority must be in 1 to 10 digits only")
    ])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None

class ApIDocumentationGuideFormSearch(FlaskForm):
    search_element = StringField('', validators=[
        Optional(),
        Length(min=MIN_LENGTH_3, max=MAX_LENGTH_150, message="Title length must be in 3 to 150 only"),Regexp(ALPHANUMERIC_REGEX,message="Title must contain Only alphanumeric characters and @#$()+_-/ allowed")

    ])
    class Meta:
        csrf=False


class GoldUserBalanceSearchForm(FlaskForm):
    goldGatewayId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    userId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="PaymentGateway").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid PG Id.")
    def validate_userId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")  
            
    class Meta: 
        csrf = False

     
class GoldTransactionSearchForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="Search id accepts only alphaNumeric characters")])
    goldGatewayId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    pgId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])

    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="PaymentGateway").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid PG Id.")
            
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = GoldUsers.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")       
            
    class Meta: 
        csrf = False
  
class GoldTransactionSuccessForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="Search id accepts only alphaNumeric characters")])
    goldGatewayId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    pgId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="PaymentGateway").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid Gateway Id.")
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = GoldUsers.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")       
    class Meta: 
        csrf = False

class GoldTransactionPendingForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="Search id accepts only alphaNumeric characters")])
    goldGatewayId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    pgId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="PaymentGateway").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid Gateway Id.")
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = GoldUsers.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")       
    class Meta: 
        csrf = False

class GoldBuyPaymentFailedForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="Search id accepts only alphaNumeric characters")])
    goldGatewayId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    pgId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="PaymentGateway").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid Gateway Id.")
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = GoldUsers.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")       
    class Meta: 
        csrf = False

class GoldPendingPaymentForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="Search id accepts only alphaNumeric characters")])
    goldGatewayId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    pgId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="PaymentGateway").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid Gateway Id.")
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = GoldUsers.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")       
    class Meta: 
        csrf = False

class GoldTransactionFailForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="Search id accepts only alphaNumeric characters")])
    goldGatewayId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    pgId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="PaymentGateway").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid Gateway Id.")
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = GoldUsers.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")       
    class Meta: 
        csrf = False

class GoldSellAllTransactionSearchForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="Search id accepts only alphaNumeric characters")])
    goldGatewayId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])

    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="Gold").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid PG Id.")

    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")

    class Meta: 
        csrf = False

class GoldSellSuccessTransactionSearchForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="Search id accepts only alphaNumeric characters")])
    goldGatewayId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])

    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="Gold").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid PG Id.")
            
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
            
    class Meta: 
        csrf = False

class GoldSellProcessTransactionSearchForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="Search id accepts only alphaNumeric characters")])
    goldGatewayId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])

    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="Gold").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid PG Id.")
            
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
            
    class Meta: 
        csrf = False

class GoldSellFailedTransactionSearchForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    searchId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="Search id accepts only alphaNumeric characters")])
    goldGatewayId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])

    def validate_pgId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status__in=[0,1],transactionType="Gold").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid PG Id.")
            
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
            
    class Meta: 
        csrf = False

class GoldMasterForm(FlaskForm): 
    goldTransactionApiIdsList = SelectMultipleField('', choices=[], validate_choice=False,validators=[DataRequired(message="Gold Transaction Api is Required")])
    paymentGatewayApiId = SelectField('', choices=[], validate_choice=False,validators=[DataRequired(message="Payment Gateway is Required")])

    def __init__(self, *args, current_id=None, original_data=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        self.original_data = original_data or {}

    def validate_goldTransactionApiIdsList(self, field):
        try:
            object_ids = []
            for val in field.data:
                if not ObjectId.is_valid(val):
                    raise ValidationError(f"Invalid Transaction API ID")
                object_ids.append(ObjectId(val))

            valid_count = TransactionAPI.objects(id__in=object_ids, status__in=[0, 1]).count()
            if valid_count != len(object_ids):
                raise ValidationError("One or more selected APIs are invalid.")

            current_set = set(str(i) for i in object_ids)
            existing_records = AssignGoldPaymentGateway.objects(status__in=[0, 1])

            if self.current_id:
                existing_records = existing_records.filter(id__ne=ObjectId(self.current_id))

            for record in existing_records:
                record_ids = set(str(api.id) for api in record.goldTransactionApiIdsList)
                if current_set & record_ids:
                    raise ValidationError("One or more selected Gold APIs are already assigned in another record.")
        except bson_errors.InvalidId:
            raise ValidationError("Invalid ObjectId format in goldTransactionApiIdsList.")

    def validate_paymentGatewayApiId(self, field):
        submitted_pg_id = str(field.data)
        original_pg_id = str(self.original_data.get("paymentGatewayApiId", ""))

        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid Payment Gateway Id.")

        if submitted_pg_id == original_pg_id:
            return

        existing = AssignGoldPaymentGateway.objects(paymentGatewayApiId=submitted_pg_id,status__in=[0, 1]).first()

        if existing and str(existing.id) != self.current_id:
            raise ValidationError('This Payment Gateway is already assigned.')

    class Meta:
        csrf = False


class CreateProductForm(FlaskForm):
    productName = StringField('',validators=[DataRequired(), Length(min=3, max=75,message="Please enter a productName between 3 and 75 numeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="Product Name must contain only alphanumeric characters, spaces, and specific special characters: @#$()+_-/")])
    payinPaymentGatewayId = SelectField('',choices=[], validate_choice=False,validators=[DataRequired(message = "payinPaymentGatewayId is required")])
    sku = StringField('',validators=[DataRequired(), Length(min=3, max=75,message="Please enter a sku between 3 and 75 characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="Sku must contain only  alphanumeric characters, spaces, and specific special characters: @#$()+_-/")])
    price = StringField('',validators=[Optional(), Length(min=1, max=10,message="Please enter price between 1 and 10 numeric characters"),Regexp(r'^\d+(\.\d+)*$', message="price contains only numeric characters")])
    startingPrice = StringField('',validators=[DataRequired(), Length(min=1, max=10,message="Please enter startingPrice between 1 and 10 numeric characters"),Regexp(r'^\d+(\.\d+)?$', message="startingPrice contains only numeric characters")])
    endingPrice = StringField('',validators=[DataRequired(), Length(min=1, max=10,message="Please enter a endingPrice between 1 and 10 numeric characters"),Regexp(r'^\d+(\.\d+)?$', message="endingPrice contains only numeric characters")])
    description = StringField('',validators=[Optional(), Length(min=1, max=150,message="Please enter a description between 1 and 150 characters")])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)


    def validate_productName(self, field):
        existing = Products.objects(productName=field.data,status__in=[0, 1]).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Product Name already exists.')
    

    class Meta:
        csrf = False

class SearchProduct(FlaskForm):
    search_element = StringField('',validators=[Optional(), Length(min=3, max=75,message="Search Product Name contain between 3 and 75 numeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="Search Product Name contains only Alphanumeric characters and allows some symbols.")])

    class Meta:
        csrf = False


class ThirdPartyIntigrationForm(FlaskForm):
    name = StringField('',validators=[DataRequired(message="serviceName is required."),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="Name must be between 3 and 75 characters."), Regexp(ALPHANUMERIC_REGEX, message="Name can only contain alphanumeric characters and :@#$()+_-/.")])  
    ipAddress = StringField('',validators=[DataRequired(), Length(min=3, max=75,message="Please enter a Ip Address between 1 and 16 numeric characters"),Regexp(r'^\d+(\.\d+)*$', message="IP Address contains only numeric characters and allows multiple dots.")])  
    trnIdentifier= StringField('',validators=[DataRequired(message="Transaction is required."),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_32, message="Transaction must be between 3 and 75 characters."), Regexp(ALPHANUMERIC_REGEX, message="Transaction can only contain alphanumeric characters and :@#$()+_-/.")])  
    enablePayin = BooleanField('')      
    payinPaymentGatewayId = SelectField('', choices=[],validate_choice=False, validators=[Optional()])
    payinWebhook =  StringField('',validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="payinWebhook must be between 3 and 75 characters."), Regexp(ALPHANUMERIC_REGEX, message="payinWebhook can only contain alphanumeric characters and :@#$()+_-/.")])  
    enablePayout = BooleanField('')
    payoutPaymentGatewayId = SelectField('', choices=[],validate_choice=False, validators=[Optional()])
    payoutWebhook = StringField('',validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="payoutWebhook must be between 3 and 75 characters."), Regexp(ALPHANUMERIC_REGEX, message="payoutWebhook can only contain alphanumeric characters and :@#$()+_-/.")])
    payoutVAWebhook =StringField('',validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="payoutVAWebhook must be between 3 and 75 characters."), Regexp(ALPHANUMERIC_REGEX, message="payoutVAWebhook can only contain alphanumeric characters and :@#$()+_-/.")])
    payoutValidationWebhook = StringField('',validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="payoutValidationWebhook must be between 3 and 75 characters."), Regexp(ALPHANUMERIC_REGEX, message="payoutValidationWebhook can only contain alphanumeric characters and :@#$()+_-/.")])
    payoutAlertsWebhook =StringField('',validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="payoutAlertsWebhook must be between 3 and 75 characters."), Regexp(ALPHANUMERIC_REGEX, message="payoutAlertsWebhook can only contain alphanumeric characters and :@#$()+_-/.")])
        
        
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None

        if self.enablePayin.data==True:
            self.payinPaymentGatewayId.validators = [
                v for v in self.payinPaymentGatewayId.validators if not isinstance(v, Optional)
            ]
            self.payinPaymentGatewayId.validators.append(DataRequired(message="Payin Payment Gateway ID is required"))
   
        if self.enablePayin.data==True:
            self.payinWebhook.validators = [
                v for v in self.payinWebhook.validators if not isinstance(v, Optional)
            ]
            self.payinWebhook.validators.append(DataRequired(message="Payin WebHook is Required"))

        if self.enablePayout.data==True:
            self.payoutPaymentGatewayId.validators = [
                v for v in self.payoutPaymentGatewayId.validators if not isinstance(v, Optional)
            ]
            self.payoutPaymentGatewayId.validators.append(DataRequired(message="Payout Payment Gateway ID is Required"))

        
        if self.enablePayout.data==True:
            self.payoutWebhook.validators = [
                v for v in self.payoutWebhook.validators if not isinstance(v, Optional)
            ]
            self.payoutWebhook.validators.append(DataRequired(message="payout webHook is Required"))
        
        if self.enablePayout.data==True:
            self.payoutVAWebhook.validators = [
                v for v in self.payoutVAWebhook.validators if not isinstance(v, Optional)
            ]
            self.payoutVAWebhook.validators.append(DataRequired(message="PayoutVA WebHook is Required"))
        
        if self.enablePayout.data==True:
            self.payoutValidationWebhook.validators = [
                v for v in self.payoutValidationWebhook.validators if not isinstance(v, Optional)
            ]
            self.payoutValidationWebhook.validators.append(DataRequired(message="Payout Validation Webhook is Required"))
        
        if self.enablePayout.data==True:
            self.payoutAlertsWebhook.validators = [
                v for v in self.payoutAlertsWebhook.validators if not isinstance(v, Optional)
            ]
            self.payoutAlertsWebhook.validators.append(DataRequired(message="Payout Alerts Webhook is Required"))
    
    def validate_name(self, field):
            existing = ThirdPartyMerchants.objects(name=field.data,status__in=[0, 1]).first()
            if existing and str(existing.id) != self.current_id:
                raise ValidationError('Site Name already exists.')
                
    def validate_payinPaymentGatewayId(self, field):
        if self.enablePayin.data=="True":
            if not field.data:
                raise ValidationError("Please select a Payin Payment Gateway.")
        if field.data:
            pg = TransactionAPI.objects(id=field.data, transactionType="PaymentGateway", status__in=[0,1]).first()
            if not pg:
                raise ValidationError("Please select a valid Payin Payment Gateway.")
                
    def validate_payoutPaymentGatewayId(self, field):
        if self.enablePayout.data=="True":
            if not field.data:
                raise ValidationError("Please select a Payout Payment Gateway.")
        if field.data:
            pg = TransactionAPI.objects(id=field.data, transactionType="Payout", status__in=[0,1]).first()
            if not pg:
                raise ValidationError("Please select a valid Payout Payment Gateway.")
            
class CreateApiSecurityList(FlaskForm):
    userId = SelectField('',choices=[], validate_choice=False,validators=[DataRequired(message = "User Name is required")])
    apiType = SelectField('',choices=[], validate_choice=False,validators=[DataRequired(message = "Api Type is required")])
    ipAddress = StringField('',validators=[DataRequired(), Length(min=3, max=75,message="Please enter a Ip Address between 1 and 16 numeric characters"),Regexp(r'^\d+(\.\d+)*$', message="IP Address contains only numeric characters and allows multiple dots.")])
    ipAddress2 = StringField('',validators=[Optional(), Length(min=1, max=16,message="Please enter a Ip Address 2 between 1 and 16 numeric characters"),Regexp(r'^\d+(\.\d+)*$', message="IP Address 2 contains only numeric characters and allows multiple dots.")])
    ipAddress3 = StringField('',validators=[Optional(), Length(min=1, max=16,message="Please enter a Ip Address 3 between 1 and 16 numeric characters"),Regexp(r'^\d+(\.\d+)*$', message="IP Address 3 contains only numeric characters and allows multiple dots.")])
    ipAddress4 = StringField('',validators=[Optional(), Length(min=1, max=16,message="Please enter a Ip Address 4 between 1 and 16 numeric characters"),Regexp(r'^\d+(\.\d+)*$', message="IP Address 4 contains only numeric characters and allows multiple dots.")])
    callBackUrl = StringField('',validators=[Optional(), Length(min=3, max=75,message="Please enter a callBackUrl between 3 and 75 numeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="callBackUrl contains only Alphanumeric characters and allows some symbols.")])
    returnUrl = StringField('',validators=[Optional(), Length(min=3, max=75,message="Please enter a ReturnUrl between 3 and 75 numeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="ReturnUrl contains only Alphanumeric characters and allows some symbols")])
    validFor = SelectField('',choices=[], validate_choice=False,validators=[DataRequired(message = "validFor is required")])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)
        
    def validate_userId(self, field):
        user = Users.objects(id=field.data).first()
        if user:
            api_type = self.apiType.data
            if api_type:
                existing = ApiSecurities.objects(
                    userId=field.data,
                    apiType=api_type,
                    status__in=[0, 1]
                ).first()
                if existing and str(existing.id) != self.current_id:
                    raise ValidationError('User already exists with this API type')
    
    class Meta:
        csrf = False

class SearchApiType(FlaskForm):
    search_element = StringField('',validators=[Optional(), Length(min=3, max=75,message="SearchApiType contain between 3 and 75 numeric characters"),Regexp(r'^[a-zA-Z0-9\s@#$()+_\-/]+$', message="SearchApiType contains only Alphanumeric characters and allows some symbols.")])

    class Meta:
        csrf = False

     
class MultipleAppSitesForm(FlaskForm):
    siteTitle = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message="SiteTitle must be 3 to 75 characters"),Regexp(ALPHANUMERIC_REGEX, message="SiteTitle can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    siteCode = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_15,message="SiteTitle must be 3 to 75 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPECIAL_CHARACTERS, message="SiteTitle can only contain letters, numbers, and spaces")])
    siteUrl = StringField('', validators=[
        Optional(),  # Optional field
        Regexp(URL_REGEX, message="Please enter a valid URL (like https://example.com)")
    ])
    enableMerchantSettlement = BooleanField('Enable Merchant Settlement', default=False)
    instantSettlementType = BooleanField("Instant Settlement Type Enable", default=False)
    paylaterSettlementType = BooleanField("Paylater Settlement Type Enable", default=False)
    defaultSettlement = SelectField(
        "Default Settlement",
        choices=[
            ("", "Select Default"),
            ("True", "Instant"),
            ("False", "T+1")
        ],
        validators=[Optional()]
    )
    defaultSelect = SelectField(
        "Default Select",
        choices=[
            ("", "Select Default"),
            ("instant", "Instant"),
            ("paylater", "T+1")
        ],
        validators=[Optional()]
    )
    
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_siteTitle(self, field):
        existing = MultipleAppSites.objects(siteTitle=field.data,status__in=[0,1]).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Site Title already exists.')

    def validate_siteCode(self, field):
        existing = MultipleAppSites.objects(siteCode=field.data,status__in=[0,1]).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Site Code already exists.')
    
class MultipleAppSitesSearchForm(FlaskForm):
    search_element = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message="SiteTitle must be 3 to 75 characters"),Regexp(ALPHANUMERIC_REGEX, message="SiteTitle can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
   
    class Meta:
        csrf = False  

class MobileApkVersionsForm(FlaskForm):
    siteId = SelectField('', choices=[],validate_choice=False, validators=[DataRequired("Site Id is Required")])
    versionNumber = StringField('Version Number', validators=[
        DataRequired("Version number is Required"),
        Length(min=MIN_LENGTH_1, max=MAX_LENGTH_15,message = INVALID_FORMAT_MESSAGE),Regexp(ALPHANUMERIC_REGEX_WITH_DOT,message=INVALID_LENGTH_MESSAGE)
        
    ])
    downloadLink = StringField('Download Link', validators=[
        DataRequired("Download Link is Required"),
        Length(min=MIN_LENGTH_1, max=MAX_LENGTH_150,message = INVALID_FORMAT_MESSAGE),Regexp(ALPHANUMERIC_REGEX,message=INVALID_FORMAT_MESSAGE)
        
    ])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        
    def validate_siteId(self, field):
        if not ObjectId.is_valid(field.data):
            raise ValidationError("Invalid SiteId")
        matchultiple_app_sites_queryset =  MultipleAppSites.objects(id=field.data,status__in=[0,1]).first()
        if not matchultiple_app_sites_queryset:
            raise ValidationError("Selected siteId is not valid.")


class MobileApkVersionsFormSearch(FlaskForm):
    search_element = StringField('', validators=[
        Optional(),
        Length(min=MIN_LENGTH_1, max=MAX_LENGTH_15, message="Search element length must be in 1 to 15"),Regexp(ALPHANUMERIC_REGEX_WITH_DOT,message="Search element must contain alpha numeric only with dot")

    ])
    class Meta:
        csrf=False

class BannerForm(FlaskForm):
    name = StringField('', validators=[ DataRequired(message="Name is Required"), Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="Name must be 3 to 75 characters only"),Regexp(ALPHANUMERIC_REGEX, message="Name can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    googleScript = StringField('', validators=[Optional(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_150, message="Google Script must be between 1 and 150 characters.")])
    sorting = IntegerField('', validators=[ DataRequired(message="Sorting is Required"), NumberRange(min=1, max=99999, message="Sorting must be between 1 and 150") ])
    isGrievance = BooleanField('',)  
    isBanner = BooleanField('')
    externalLink = StringField('', validators=[ Optional(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_150,message = "External Link must be in 1 to 150 length only"),Regexp(ALPHANUMERIC_REGEX,message="External Link can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    image = FileField('', validators=[Optional(),FileAllowed(['jpg', 'jpeg', 'png'], INVALID_Image_MESSAGE)])

    class Meta:
        csrf = False

class BannersSearchForm(FlaskForm):
    search_element = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message="Search Element must be in 3 to 75 characters only"),Regexp(ALPHANUMERIC_REGEX, message="Search Element can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
   
    class Meta:
        csrf = False 

def validate_email_list(form, field):
    emails = [email.strip() for email in field.data.split(",") if email.strip()]
    for email in emails:
        if not re.match(CONTACT_EMAIL_REGEX, email):
            raise ValidationError(f"Please enter valid email addresses")

def validate_mobile_numbers(form, field):
    numbers = [num.strip() for num in field.data.split(",") if num.strip()]
    for number in numbers:
        if not re.match(CONTACT_PHONE_NUMBER_REGEX, number):
            raise ValidationError(f"Please enter valid 10-digit mobile numbers ")
class SenderMailsForm(FlaskForm):
    mailType = SelectField(
        'Mail Type',
        choices=[
            ('Settlement Mail', 'Settlement Mail'),
            ('Payin Transactions Mail', 'Payin Transactions Mail'),
            ('Payout Transactions Mail', 'Payout Transactions Mail'),
            ('Overall Transactions Mail', 'Overall Transactions Mail'),
            ('Profile Setup', 'Profile Setup'),
            ('Merchant KYC', 'Merchant KYC'),
            ('Wallet Adjustment', 'Wallet Adjustment'),
            ('User Registration', 'User Registration'),
            ('Utility', 'Utility'),
            ('Payout_Insuficiant', 'Payout Insufficient'),
            ('API Setup', 'API Setup'),
            ('Staff', 'Staff'),
            ('Ip Address', 'Ip Address')
        ],
        validators=[DataRequired(message="Please select a mail type.")]
    )
    mailsList = StringField('Sender Emails',validators=[DataRequired(message="Please enter at least one sender email."),validate_email_list])
    mobileNumber = StringField('Mobile Numbers',validators=[DataRequired(message="Please enter at least one mobile number."),validate_mobile_numbers])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_mailType(self, field):
        existing = SenderMails.objects(mailType=field.data,status__nin=[2]).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('MailType already exists.')

class SenderMailsSearchForm(FlaskForm):
    mailType = SelectField(
            "Mail Type",
            choices=[
                ("", "Select Mail Type"),
                ("Settlement Mail", "Settlement Mail"),
                ("Payin Transactions Mail", "Payin Transactions Mail"),
                ("Payout Transactions Mail", "Payout Transactions Mail"),
                ("Overall Transactions Mail", "Overall Transactions Mail"),
                ("Profile Setup", "Profile Setup"),
                ("Merchant KYC", "Merchant KYC"),
                ("Wallet Adjustment", "Wallet Adjustment"),
                ("User Registration", "User Registration"),
                ("Utility", "Utility"),
                ("Payout_Insuficiant", "Payout Insufficient"),
                ("API Setup", "API Setup"),
                ("Staff", "Staff"),
                ('Ip Address', 'Ip Address')
            ],
            validators=[Optional()]
        )
    class Meta:
        csrf = False



class TicketForm(FlaskForm):
    name = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_75,message="Category Name must be 3 to 75 characters"),Regexp(ALPHANUMERIC_REGEX, message="Category Name can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    priority = IntegerField('', validators=[
        DataRequired(),
        NumberRange(min=0, max=9999, message="Priority must be between 0 and 9999.")
    ])
    icon = FileField('', validators=[Optional(),FileAllowed(['jpg', 'jpeg', 'png'], INVALID_Image_MESSAGE)])

   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_name(self, field):
        existing = TicketCategory.objects(name=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Name already exists.')      


class TicketSearchForm(FlaskForm):
    search_element = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message="Category Name must be 3 to 75 characters"),Regexp(ALPHANUMERIC_REGEX, message="Category Name can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
   
    class Meta:
        csrf = False  

class TicketSubForm(FlaskForm):
    name = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_75,message="Sub Category Name must be 3 to 75 characters"),Regexp(ALPHANUMERIC_REGEX, message="Sub Category Name can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    categoryId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    priority = IntegerField('', validators=[
        DataRequired(),
        NumberRange(min=0, max=9999, message="Priority must be between 0 and 9999.")
    ])
    icon = FileField('', validators=[Optional(),FileAllowed(['jpg', 'jpeg', 'png'], INVALID_Image_MESSAGE)])

   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_name(self, field):
        existing = TicketSubCategory.objects(name=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Name already exists.')

    def validate_categoryId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid categoryId. Please select a valid categoryId.")
        
        ticket_category_queryset = TicketCategory.objects(id=field.data,status__in=[0,1]).first()
        if not ticket_category_queryset:
            raise ValidationError("Selected categoryId is not valid.")


class TicketSubSearchForm(FlaskForm):
    ticket_sub_search_element = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message="Sub Category Name must be 3 to 75 characters"),Regexp(ALPHANUMERIC_REGEX, message="Sub Category Name can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
   
    class Meta:
        csrf = False  

class TicketChildForm(FlaskForm):
    name = StringField('', validators=[DataRequired(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_75,message="Child Category Name must be 3 to 75 characters"),Regexp(ALPHANUMERIC_REGEX, message="Child Category Name can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    subCategoryId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    priority = IntegerField('', validators=[
        DataRequired(),
        NumberRange(min=0, max=9999, message="Priority must be between 0 and 9999.")
    ])
    icon = FileField('', validators=[Optional(),FileAllowed(['jpg', 'jpeg', 'png'], INVALID_Image_MESSAGE)])

   
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)

    def validate_name(self, field):
        existing = TicketChildCategory.objects(name=field.data).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('Name already exists.')

    def validate_subCategoryId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid subCategoryId. Please select a valid subCategoryId.")
        
            sub_category_queryset = TicketSubCategory.objects(id=field.data,status__in=[0,1]).first()
            if not sub_category_queryset:
                raise ValidationError("Selected subCategoryId is not valid.")

class TicketChildSearchForm(FlaskForm):
    ticket_child_search_element = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message="Child Category Name must be 3 to 75 characters"),Regexp(ALPHANUMERIC_REGEX, message="Child Category Name can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
   
    class Meta:
        csrf = False 

class ComplaintsSearchForm(FlaskForm):
    startDate = StringField('',validators=[
        Optional(),
        Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[
        Optional(),
        Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    
    class Meta:
        csrf = False
        

class SmsLogsForm(FlaskForm):
    name = StringField('', validators=[ Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message = "Name length in between 3 to 15 only"),Regexp(ALPHANUMERIC_REGEX,message="Name must contain only alphanumeric characters and @#$()+_-/ allowed") ])
    phoneNumber  = StringField('', validators=[ Optional(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_10,message = "Phone number must be 1 and 10 digits only"),Regexp(PHONE_NUMBER_REGEX,message="Phone number must be in numeric and 1 and 10 digits only")])

    class Meta:
        csrf = False


class AdminOtpLogsForm(FlaskForm):
    name = StringField('', validators=[ Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message = "Name length in between 3 to 15 only"),Regexp(ALPHANUMERIC_REGEX,message="Name must contain only alphanumeric characters and @#$()+_-/ allowed") ])

    class Meta:
        csrf = False

class ApiLogsForm(FlaskForm):
    walletType = SelectField('', choices=[ ("", "Select"), ("payin", "payin"), ("payout", "payout") ],validators=[ Optional() ], coerce=str)

    class Meta:
        csrf = False

class ClientLogsForm(FlaskForm):
    walletType = SelectField('', choices=[ ("", "Select"), ("payin", "payin"), ("payout", "payout") ],validators=[ Optional() ], coerce=str)

    class Meta:
        csrf = False

class AdminLogsForm(FlaskForm):
    name = StringField('', validators=[ Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message = "Name length in between 3 to 15 only"),Regexp(ALPHANUMERIC_REGEX,message="Name must contain only alphanumeric characters and @#$()+_-/ allowed") ])

    class Meta:
        csrf = False

class StaffMembersForm(FlaskForm):
    email = StringField('', validators=[DataRequired(),Length(min=6, max=100),Regexp(CONTACT_EMAIL_REGEX, message="Please enter a valid email address.")])
    userName = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75),Regexp(ALPHANUMERIC_REGEX, message="UserName must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    phoneNumber =  StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_1, max=MIN_LENGTH_10),Regexp(PHONE_NUMBER_REGEX, message="Phone Number must be in numeric and 1 and 10 digits only")])
    # password =  StringField('', validators=[DataRequired(),Length(min=8, max=30),Regexp(PASSWORD_REGEX, message="Password must be 8-30 characters long, include at least one uppercase letter, one lowercase letter, one number, and one special character.")])
    password = StringField('')
    roleId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired()])
    authenticationEnabled = BooleanField('')
    
    def __init__(self, *args, **kwargs):
        self.is_update = kwargs.pop('is_update', False)
        super(StaffMembersForm, self).__init__(*args, **kwargs)

        if self.is_update:
            
            self.password.validators = []
        else:
           
            self.password.validators = [
                DataRequired(),
                Length(min=8, max=30),
                Regexp(PASSWORD_REGEX, message="Password must be 8-30 characters long, include at least one uppercase letter, one lowercase letter, one number, and one special character.")
            ]
            
    def validate_roleId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid RoleId.")
            roles_queryset = Roles.objects(id=field.data,status__in=[0,1]).first()
            if not roles_queryset:
                raise ValidationError("Please select a valid RoleId.")

    class Meta:
        csrf = False

class StaffMembersSearchForm(FlaskForm):
    search_element = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75),Regexp(ALPHANUMERIC_REGEX, message="Search field must be 3 to 75 characters long and can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
   
    class Meta:
        csrf = False

class AdminRoleForm(FlaskForm):
	roleName = StringField("Role Name",validators=[DataRequired(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="Role Name must be 3 to 75 characters long"),Regexp(ALPHANUMERIC_REGEX,
				message="Role Name must contain only alphanumeric characters, spaces, and specific special characters: @#$()+_-/")])
	
	def __init__(self, *args, current_id=None, **kwargs):
		super().__init__(*args, **kwargs)
		self.current_id = str(current_id) if current_id else None
		# self.process(*args, **kwargs)

	def validate_roleName(self, field):
		existing = Roles.objects(roleName=field.data).first()
		if existing and str(existing.id) != self.current_id:
			raise ValidationError('Role Name already exists.')

class AdminRoleFormSearch(FlaskForm):
	search_element = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="Role Name must be 3 to 75 characters long"),
		Regexp(ALPHANUMERIC_REGEX, message="Role Name can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")
	])
	
	class Meta:
		csrf = False

class CreateAdminIPAddressForm(FlaskForm):
    ipAddress = StringField('',validators=[DataRequired(), Length(min=1, max=16,message="IP Address must be between 1 and 16 characters"),Regexp(r'^\d+(\.\d+)*$', message="IP Address contains only numeric characters and allows multiple dots.")])

    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None
        # self.process(*args, **kwargs)
 
    def validate_ipAddress(self, field):
        existing = AdminIpAdress.objects(ipAddress=field.data,status__in=[0,1]).first()
        if existing and str(existing.id) != self.current_id:
            raise ValidationError('IP Address already exists.')


    class Meta:
        csrf = False 

class documentListForm(FlaskForm):
    documentName = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75,message="Document name must contain 3 to 75 character"),Regexp(ALPHANUMERIC_REGEX, message="Document Name contains Only alphanumeric and space and special characters @#$()+_-/.")])
    class Meta:
        csrf = False 

class documentFormSearch(FlaskForm):
    search_element = StringField('',validators=[Optional(),
            Length(min=MIN_LENGTH_3,max=MAX_LENGTH_75, message="Search field length must contain 3 to 75 characters"),
            Regexp(ALPHANUMERIC_REGEX, message="Search field can only contain letters, numbers, spaces, and special characters: @ # $ ( ) + _ - / .")])
    class Meta:
        csrf = False

  
class OTPForm(FlaskForm):
    otpCode = StringField('',validators=[DataRequired(message="OTP is required."),Length(min=4, max=6, message="OTP must be between 4 and 6 digits."),Regexp('^[0-9]+$', message="OTP must contain only numbers.")])
    class Meta:
        csrf = False 

############################################################################
#############################################################################

class AdminBalanceUpdateForm(FlaskForm):
    transferType = SelectField("", choices=["Payout", "Payin"], validators=[DataRequired()])
    amount = StringField('',validators=[DataRequired(), Length(min=1, max=10,message="Amount must contains between 1 and 10 numeric characters"),Regexp(r'([0-9]+([.][0-9]*)?|[.][0-9])', message="Amount contains only numeric characters")])
    comment = StringField('', validators=[DataRequired(),Length(min=3, max=75, message="comment length can be between 3 to 75 "),
            Regexp(ALPHANUMERIC_REGEX, message="comment can contain only alphanumeric characters and @#$()+_\-\/.")])

class AutoCollectLedgerSearchForm(FlaskForm): ### autocollectledger also
    startDate = StringField('',validators=[Optional(),Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[Optional(),Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    orderId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_4, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="SearchId accepts only AlphaNumeric Characters")])
   
    class Meta:
        csrf = False

class PaymentGatewaybeneForm(FlaskForm):
    paymentGatewayId = SelectField(
        "Payment Gateway",
        choices=[], 
        validators=[DataRequired(message="Please select a Payment Gateway")]
    )
        
class NameFormSearch(FlaskForm):
    search_element = StringField('',validators=[Optional(),
    Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="Please enter a Search Name between 3 and 75 numeric characters"),
    Regexp(ALPHANUMERIC_REGEX, message=("Search Name contains only Alphanumeric characters and allows some symbols."))])
        
    class Meta:
        csrf = False

class SiteAssignPaymentGatewaySearchForm(FlaskForm):
    paymentModeId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message='Payment mode is required.')])
    settlementType = SelectField('', choices=[("","Select"), ("True","True"),("False","False")],validators=[DataRequired(message='Settlement type is required')],coerce=str)
            
    def validate_paymentModeId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Payment Id.")
            payment_mode_queryset = PaymentMode.objects(id=field.data,status__nin=[2]).first()
            if not payment_mode_queryset:
                raise ValidationError("Please select a Valid Payment Id")
            
    class Meta:
        csrf = False
   
class AdminChangePasswordForm(FlaskForm):
    oldPassword =  StringField('', validators=[DataRequired(),Length(min=6, max=30),Regexp(PASSWORD_REGEX, message="Password must be 6-30 characters long, include at least one uppercase letter, one lowercase letter, one number, and one special character.")])
    newPassword =  StringField('', validators=[DataRequired(),Length(min=6, max=30),Regexp(PASSWORD_REGEX, message="Password must be 6-30 characters long, include at least one uppercase letter, one lowercase letter, one number, and one special character.")])
    confirmNewPassword =  StringField('', validators=[DataRequired(),Length(min=6, max=30),Regexp(PASSWORD_REGEX, message="Password must be 6-30 characters long, include at least one uppercase letter, one lowercase letter, one number, and one special character."), EqualTo('newPassword', message='New password and Confirm Password must match')])

class AddFilePGSettlements(FlaskForm):
    pgSettlementFile = FileField('', validators=[FileRequired(message="Please upload a file."),FileAllowed(['xls', 'xlsx', 'csv'], message = "Invalid Format, Only .xls, .xlsx, or .csv files are allowed.")])
    class Meta:
        csrf = False

class PayoutSettlementReportForm(FlaskForm):
    startDate = StringField('',validators=[Optional(),Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    orderId = StringField('', validators=[Optional(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_32,message="SearchId Must be between 6 and 35 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="SearchId accepts only AlphaNumeric Characters")])
    merchantId = SelectField('', choices=[],validate_choice=False , validators=[Optional()])

    class Meta:
        csrf = False

class BalancePayinReportsSearchForm(FlaskForm):      
    payin_selectedDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    payin_merchantId = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    payin_merchantType = SelectField('', choices=[
        ("",""),
        ("Super Distributor","Super Distributor"),
        ("Master Distributor","Master Distributor"),
        ("Area Distributor","Area Distributor"),
        ("Retailer","Retailer"),
        ("customer","customer")
        ],validators=[Optional()])

    def validate_payin_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
    class Meta:
        csrf = False    

class PayinSettlementSearchForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp(r"^\d{2}-\d{2}-\d{4}( \d{2}:\d{2})?$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}( \d{2}:\d{2})?$", message="Date must be in DD-MM-YYYY format")]) #  date and time format 
    paymentGatewayId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message="Payment gateway id is required")]) 

    def validate_paymentGatewayId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data):
                raise ValidationError("Invalid PG Id.")
            pg_queryset = TransactionAPI.objects(id=field.data,status=1,transactionType="PaymentGateway").first()
            if not pg_queryset:
                raise ValidationError("Please select a valid PG Id.")

def file_size_limit(max_size_in_mb):
    max_bytes = max_size_in_mb * 1024 * 1024

    def _file_size_limit(form, field):
        if field.data:
            file = field.data
            file.seek(0, 2)  # Seek to the end of the file
            size = file.tell()
            file.seek(0)  # Reset file pointer to the start
            if size > max_bytes:
                raise ValidationError(f"Image size must be less than {max_size_in_mb}MB.")
    return _file_size_limit

class GenerateCommissionSearchForm(FlaskForm):
    selectYear = SelectField('', choices=[],validate_choice=False, validators=[Optional()])
    selectMonth = SelectField("",choices=[("January", "January"),("February", "February"),("March", "March"),("April", "April"),("May", "May"),("June", "June"),("July", "July"),("August", "August"),("September", "September"),("October", "October"),("November", "November"),("December", "December")],validate_choice=False,validators=[Optional()])

    def validate_selectYear(self, field):
        current_year = datetime.datetime.now().year
        if str(field.data) != str(current_year) and str(field.data) != str(current_year-1):
            raise ValidationError("Invalid Year")

    class Meta:
        csrf = False

class settlementcommissionslistSearchForm(FlaskForm):
    selectYear = SelectField('', choices=[],validate_choice=False, validators=[Optional()])
    selectMonth = SelectField("",choices=[("January", "January"),("February", "February"),("March", "March"),("April", "April"),("May", "May"),("June", "June"),("July", "July"),("August", "August"),("September", "September"),("October", "October"),("November", "November"),("December", "December")],validate_choice=False,validators=[Optional()])

    def validate_selectYear(self, field):
        current_year = datetime.datetime.now().year
        if str(field.data) != str(current_year) and str(field.data) != str(current_year-1):
            raise ValidationError("Invalid Year")

    class Meta:
        csrf = False

class UpdateGeneratedCommisionForm(FlaskForm):
    gstValue = FloatField("", validators=[DataRequired(), NumberRange(min=0),Regexp(DECIMALPOINT_REGEX, message=INVALID_FORMAT_MESSAGE)])
    tdsValue = FloatField("", validators=[DataRequired(), NumberRange(min=0), Regexp(DECIMALPOINT_REGEX, message=INVALID_FORMAT_MESSAGE)])
    def __init__(self, *args, current_id=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.current_id = str(current_id) if current_id else None

class RemarkForm(FlaskForm):
    remark = StringField('', validators=[DataRequired(),Length(min=MIN_LENGTH_3, max=MAX_LENGTH_75, message="remark length can be between 3 to 75 "),
            Regexp(ALPHANUMERIC_REGEX, message="remark can contain only alphanumeric characters and @#$()+_\-\/.")])

class MerchantLogsForm(FlaskForm):
    name = SelectField('', choices=[],validate_choice=False,validators=[Optional()])
    phoneNumber  = StringField('', validators=[ Optional(), Length(min=MIN_LENGTH_1, max=MAX_LENGTH_10,message = "Phone number must be 1 and 10 digits only"),Regexp(PHONE_NUMBER_REGEX,message="Phone number must be in numeric and 1 and 10 digits only")])
    selectOs = SelectField('', choices=[ "Android","IOS", "Web" ],validators=[Optional()])

    def validate_name(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
            
    class Meta:
        csrf = False

class ChargeBackFetchForm(FlaskForm):
    chargeBackType = SelectField('', choices=[ ("wallet", "wallet"), ("utility", "utility"), ("digital_gold", "digital_gold"), ("all", "all") ],validators=[ Optional() ], coerce=str)
    pgOrderId=StringField('',validators=[DataRequired(), Length(min=6, max=MAX_LENGTH_75, message="Invalid Length"), Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="PgOrderId must be 6 to 75 characters long and can only contain letters, numbers") ])

    class Meta:
        csrf = False

class TransactionStatusForm(FlaskForm):
    merchantReferenceNumber = StringField('', validators=[DataRequired(),Length(min=6, max=MAX_LENGTH_32,message="orderId Must be between 6 and 32 characters"),Regexp(ALPHANUMERIC_WITHOUT_SPACE, message="OrderId accepts only AlphaNumeric Characters")])
    transactionStatus = SelectField(
        '', 
        choices=[
            ('', 'Select'),
            ('1', 'Success'),
            ('6', 'Success With Debit'),
            ('0', 'Failed'),
            ('4', 'Failed With Credit')
        ],validators=[DataRequired()])
    errorMessage = TextAreaField('', validators=[DataRequired()])

class SettlementForm(FlaskForm):
    settlementedRemark = TextAreaField("",validators=[DataRequired(message="Settlement reason is required."),Regexp(ALPHANUMERIC_REGEX,message="Settlement reason must contain only alphanumeric characters, spaces, and the following special characters: @#$()+_-/")])
    settlement_paymentGatewayId = HiddenField(validators=[DataRequired(message="Payment Gateway ID is required.")])
    paymentGatewayName = HiddenField(validators=[Optional()])
    settlement_startDate = HiddenField(validators=[DataRequired(message="Start Date is required.")])
    settlement_endDate = HiddenField(validators=[DataRequired(message="End Date is required.")])

    class Meta:
        csrf = False

class AdminLoginForm(FlaskForm):
    email = StringField('', validators=[Optional(),Length(min=6, max=100),Regexp(EMAIL_REGEX, message="Only Email format aab@efg.com is allowed")])
    password = StringField('', validators=[DataRequired(),Length(min=6, max=30),Regexp(PASSWORD_REGEX, message="Password must be 6-30 characters long, include at least one uppercase letter, one lowercase letter, one number, and one special character.")])


            
    # def validate_prepaidPgId(self, field):
    #     if not field.data:
    #         raise ValidationError("plaesae   select prepaid ")
    #     if field.data:
    #         if not ObjectId.is_valid(field.data): 
    #             raise ValidationError("Invalid Provider ID format.")
    #         payin_apis_queryset = TransactionAPI.objects(id=field.data,status__nin=[2]).first()
    #         if not payin_apis_queryset:
    #             raise ValidationError("Selected Prepaid PG API is invalid.")        

# class PrepaidMobileSetupForm(FlaskForm):
#     enablePrepaid = BooleanField("Enable Prepaid")  
#     prepaidPgId = SelectField("Prepaid PG", choices=[], validate_choice=False, validators=[Optional()])
#     prepaidProviderId = SelectField("Prepaid Provider API", choices=[], validate_choice=False, validators=[Optional()])

#     def __init__(self, *args, current_id=None, **kwargs):
#         super().__init__(*args, **kwargs)
#         self.current_id = str(current_id) if current_id else None

#     def validate_prepaidPgId(self, field):
#         if self.enablePrepaid.data:
#             if not field.data:
#                 raise ValidationError("Prepaid PG is required when 'Enable Prepaid' is selected.")
#             try:
#                 obj_id = ObjectId(field.data)
#             except:
#                 raise ValidationError("Invalid PG ID format.")
#             valid_count = TransactionAPI.objects(id=obj_id, status__in=[0, 1]).count()
#             if valid_count != 1:
#                 raise ValidationError("Selected Prepaid PG API is invalid.")

#     def validate_prepaidProviderId(self, field):
#         if self.enablePrepaid.data:
#             if not field.data:
#                 raise ValidationError("Prepaid Provider is required when 'Enable Prepaid' is selected.")
#             try:
#                 obj_id = ObjectId(field.data)
#             except:
#                 raise ValidationError("Invalid Provider ID format.")
#             valid_count = TransactionAPI.objects(id=obj_id, status__in=[0, 1]).count()
#             if valid_count != 1:
#                 raise ValidationError("Selected Prepaid Provider is invalid.")
                            
    # def validate_virtualCode(self, field):
    #     if self.transactionType.data == "Payout":
    #         field.validators.append(Optional())
    # def validate_lastSixDigits(self, field):
    #     if self.transactionType.data != "Payout":
    #         field.validators.append(Optional())
    # def validate_ifscCode(self, field):
    #     if self.transactionType.data != "Payout":
    #         field.validators.append(Optional())


class CommissionStructureForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])


class VerificationChargesListForm(FlaskForm):
    startDate = StringField('',validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])
    endDate = StringField('', validators=[ Optional(), Regexp( r"^\d{2}-\d{2}-\d{4}$", message="Date must be in DD-MM-YYYY format")])

            