o
    tUdh                     @   s(  d Z ddlmZ ddlmZ ddlmZmZ ddlm	Z	 ddl
mZ ddlmZ ddlmZ dd	lmZ dd
lZddlmZmZmZ ddlmZ e ZG dd deZG dd dejZG dd dejZG dd dejZG dd dejZ G dd dejZ!G dd dejZ"G dd dejZ#d
S )z
Accounts Forms Module

This module contains forms for user management, registration, profile updates,
role assignment, and other account-related functionality.

Author: Senior Django Developer
Date: 2024
    )forms)get_user_model)UserCreationFormUserChangeForm)ValidationError)gettext_lazy)validate_password)RegexValidator)
strip_tagsN   )RoleUserProfile)is_password_strongc                
       sD  e Zd ZdZejedddejdedddd	ed
dZej	edddej
dedddd	dZej	edddej
dedddd	dZej	edddededdgej
dedddd	dZejeddejddid	d ed!id"ZG d#d$ d$Z fd%d&Zd'd( Zd)d* Zd+d, Zd-d. Zd1 fd/d0	Z  ZS )2UserRegistrationFormz
    Enhanced user registration form with additional fields and validation.
    
    Features:
    - Email validation
    - Password strength checking
    - Terms acceptance
    - Phone number validation
    - First and last name requirements
    zEmail Address   Tform-controlEnter your email addressemailclassplaceholderautocompleteattrsz2We will send a verification email to this address.)label
max_lengthrequiredwidget	help_textz
First Name   Enter your first namez
given-name)r   r   r   r   z	Last NameEnter your last namezfamily-namezPhone Number   Fz^\+?1?\d{9,15}$zRPhone number must be entered in the format: "+999999999". Up to 15 digits allowed.)regexmessagezEnter your phone numbertel)r   r   r   
validatorsr   z0I accept the Terms of Service and Privacy Policyr   form-check-inputr   z5You must accept the terms and conditions to register.)r   r   r   error_messagesc                   @   s   e Zd ZeZdZdS )zUserRegistrationForm.Meta)r   
first_name	last_namephone_number	password1	password2N)__name__
__module____qualname__r   modelfields r4   r4   GC:\Users\vibe-look\OneDrive\Desktop\Adtlas_V\src\apps\accounts\forms.pyMetah   s    r6   c                    sf   t  j|i | | jd jjdtddd | jd jjdtddd td| jd _d	S )
z
        Initialize the form with custom styling and attributes.
        
        Args:
            *args: Variable length argument list
            **kwargs: Arbitrary keyword arguments
        r-   r   zEnter a strong passwordznew-passwordr   r.   zConfirm your passwordzrYour password must contain at least 8 characters, including uppercase, lowercase, numbers, and special characters.N)super__init__r3   r   r   update_r   selfargskwargs	__class__r4   r5   r8   l   s   zUserRegistrationForm.__init__c                 C   sV   | j d}|r)|  }tjj|d rtt	dt
d|s)tt	d|S )z
        Validate email uniqueness and format.
        
        Returns:
            str: Cleaned email address
            
        Raises:
            ValidationError: If email is invalid or already exists
        r   r   .A user with this email address already exists.z0^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$z#Please enter a valid email address.N)cleaned_datagetlowerstripr   objectsfilterexistsr   r:   rematch)r<   r   r4   r4   r5   clean_email   s   
z UserRegistrationForm.clean_emailc                 C   >   | j d}|rd|  }td|sttd|S )zn
        Validate and clean first name.
        
        Returns:
            str: Cleaned first name
        r*    ^[a-zA-Z\s\-']+$zFFirst name can only contain letters, spaces, hyphens, and apostrophes.N	rC   rD   joinsplittitlerJ   rK   r   r:   )r<   r*   r4   r4   r5   clean_first_name      z%UserRegistrationForm.clean_first_namec                 C   rM   )zl
        Validate and clean last name.
        
        Returns:
            str: Cleaned last name
        r+   rN   rO   zELast name can only contain letters, spaces, hyphens, and apostrophes.NrP   )r<   r+   r4   r4   r5   clean_last_name   rU   z$UserRegistrationForm.clean_last_namec                 C   s0   | j d}|rt| t|sttd|S )z
        Validate password strength.
        
        Returns:
            str: Cleaned password
            
        Raises:
            ValidationError: If password is not strong enough
        r-   gPassword must contain at least 8 characters with uppercase, lowercase, numbers, and special characters.N)rC   rD   r   r   r   r:   )r<   r-   r4   r4   r5   clean_password1   s   
z$UserRegistrationForm.clean_password1c                    s   t  jdd}| jd |_| jd |_| jd |_| jd |_|rH|  tjj	|d| j
ddid\}}|sH| j
drH| jd |_|  |S )
z
        Save the user instance with additional profile data.
        
        Args:
            commit: Whether to save to database
            
        Returns:
            User: Created user instance
        F)commitr   r*   r+   r,    )userdefaultsN)r7   saverC   usernamer   r*   r+   r   rG   get_or_createrD   r,   )r<   rY   r[   profilecreatedr?   r4   r5   r]      s    

zUserRegistrationForm.save)T)r/   r0   r1   __doc__r   
EmailFieldr:   
EmailInputr   	CharField	TextInputr*   r+   r	   r,   BooleanFieldCheckboxInputZterms_acceptedr6   r8   rL   rT   rV   rX   r]   __classcell__r4   r4   r?   r5   r      s    r   c                   @   &   e Zd ZdZG dd dZdd ZdS )UserUpdateFormz{
    Form for updating user basic information.
    
    Allows users to update their email, first name, and last name.
    c                   @   sV   e Zd ZeZdZejdedddej	dedddej	deddddZ
dS )	zUserUpdateForm.Meta)r   r*   r+   r   r   r   r   r   r!   r"   N)r/   r0   r1   r   r2   r3   r   rd   r:   rf   widgetsr4   r4   r4   r5   r6     s     
r6   c                 C   sN   | j d}|r%|  }tjj|dj| jj	d}|
 r%ttd|S )z
        Validate email uniqueness (excluding current user).
        
        Returns:
            str: Cleaned email address
        r   rA   pkrB   N)rC   rD   rE   rF   r   rG   rH   excludeinstancero   rI   r   r:   )r<   r   Zexisting_userr4   r4   r5   rL   '  s   zUserUpdateForm.clean_emailN)r/   r0   r1   rb   r6   rL   r4   r4   r4   r5   rk         rk   c                   @   s.   e Zd ZdZG dd dZdd Zdd ZdS )	ProfileFormz
    Form for updating user profile information.
    
    Handles profile-specific fields like bio, birth date, avatar, etc.
    c                   @   sd   e Zd ZeZdZejddedddej	ddddej
ded	d
dejdddddZdS )zProfileForm.Meta)bio
birth_dateavatarwebsiteis_profile_publicemail_notificationssms_notificationsr      zTell us about yourselfr   rowsr   r   date)r   typezEnter your website URLrl   zimage/*)r   accept)rt   ru   rw   rv   N)r/   r0   r1   r   r2   r3   r   Textarear:   	DateInputURLInput	FileInputrm   r4   r4   r4   r5   r6   D  s*    
r6   c                 C   s8   | j d}|rt| }t|dkrttd|S )zk
        Clean and validate bio field.
        
        Returns:
            str: Cleaned bio text
        rt   i  z#Bio must be 500 characters or less.N)rC   rD   r
   rF   lenr   r:   )r<   rt   r4   r4   r5   	clean_bio[  s   zProfileForm.clean_bioc                 C   sH   | j d}|r"|jdkrttdg d}|j|vr"ttd|S )zm
        Validate avatar image file.
        
        Returns:
            File: Cleaned avatar file
        rv   i  P z&Avatar image must be smaller than 5MB.)z
image/jpegz	image/pngz	image/gifz
image/webpz/Avatar must be a JPEG, PNG, GIF, or WebP image.N)rC   rD   sizer   r:   content_type)r<   rv   Zallowed_typesr4   r4   r5   clean_avatarp  s   

zProfileForm.clean_avatarN)r/   r0   r1   rb   r6   r   r   r4   r4   r4   r5   rs   =  s
    rs   c                   @   rj   )RoleFormzy
    Form for creating and editing roles.
    
    Allows administrators to manage role information and permissions.
    c                   @   sR   e Zd ZeZdZejdedddej	ddedddej
d	d
iddZdS )zRoleForm.Meta)namedescriptionpermissionsr   zEnter role namerl   r      zDescribe this roler|   r   r(   N)r/   r0   r1   r   r2   r3   r   rf   r:   r   CheckboxSelectMultiplerm   r4   r4   r4   r5   r6     s     
r6   c                 C   sr   | j d}|r7|  }tjj|d}| jjr!|j	| jjd}|
 r+ttdtd|s7ttd|S )zx
        Validate role name uniqueness and format.
        
        Returns:
            str: Cleaned role name
        r   )r   rn   z%A role with this name already exists.z^[a-zA-Z\s]+$z.Role name can only contain letters and spaces.N)rC   rD   rF   rS   r   rG   rH   rq   ro   rp   rI   r   r:   rJ   rK   )r<   r   Zexisting_roler4   r4   r5   
clean_name  s   zRoleForm.clean_nameN)r/   r0   r1   rb   r6   r   r4   r4   r4   r5   r     rr   r   c                       sN   e Zd ZdZejej ej	ddidde
de
ddZ fd	d
Z  ZS )UserRoleAssignmentFormzp
    Form for assigning roles to users.
    
    Allows administrators to select multiple roles for a user.
    r   r(   r   FzAssign Rolesz(Select the roles to assign to this user.)querysetr   r   r   r   c                    sB   | dd| _t j|i | | jr| jj | jd _dS dS )z
        Initialize form with user instance.
        
        Args:
            *args: Variable length argument list
            **kwargs: Arbitrary keyword arguments including 'user'
        r[   Nroles)popr[   r7   r8   r   allr3   initialr;   r?   r4   r5   r8     s
   zUserRoleAssignmentForm.__init__)r/   r0   r1   rb   r   ModelMultipleChoiceFieldr   rG   r   r   r:   r   r8   ri   r4   r4   r?   r5   r     s    
r   c                   @   s"  e Zd ZdZejddejdeddddd	Zej	e
j ded
ejddiddZejdedfdedfdedfdedfdedfgdejddiddZejdedfdedfdedfdedfd ed!fd"ed#fd$ed%fd&ed'fd(ed)fg	ddejddidd*Zd+S ),UserSearchFormzp
    Form for searching and filtering users.
    
    Provides search functionality for the user list view.
    d   Fr   zSearch by name, email, or phoneoffr   r   )r   r   r   z	All Rolesr   )r   r   empty_labelr   rZ   z	All UsersactivezActive UsersinactivezInactive UsersverifiedzVerified Users
unverifiedzUnverified Users)choicesr   r   z-date_joinedzNewest Firstdate_joinedzOldest Firstr   z	Email A-Zz-emailz	Email Z-Ar*   zFirst Name A-Zz-first_namezFirst Name Z-Ar+   zLast Name A-Zz
-last_namezLast Name Z-Az-last_loginz
Last Login)r   r   r   r   N)r/   r0   r1   rb   r   re   rf   r:   searchModelChoiceFieldr   rG   r   SelectroleChoiceFieldstatusorder_byr4   r4   r4   r5   r     s`    
	














r   c                   @   s   e Zd ZdZdedfdedfdedfded	fgZejeejd
dideddZ	ej
ej e eddZejdedejd
diddZdS )BulkUserActionFormz
    Form for performing bulk actions on users.
    
    Allows administrators to perform actions on multiple users at once.
    activatezActivate Selected Users
deactivatezDeactivate Selected UsersdeletezDelete Selected UsersexportzExport Selected Usersr   r   r   Action)r   r   r   zSelected Users)r   r   r   TzI confirm this actionr(   )r   r   r   N)r/   r0   r1   rb   r:   ZACTION_CHOICESr   r   r   actionr   r   rG   r   r   Zselected_usersrg   rh   confirmr4   r4   r4   r5   r      s4    




r   c                       s   e Zd ZdZejedejdeddddZejedejded	dddZ	ejed
ejdeddddZ
 fddZdd Zdd Z fddZdd Z  ZS )PasswordChangeFormzy
    Custom password change form with enhanced validation.
    
    Provides secure password changing functionality.
    zCurrent Passwordr   zEnter your current passwordrl   r   )r   r   zNew PasswordzEnter your new passwordzConfirm New PasswordzConfirm your new passwordc                    s   || _ t j|i | dS )z
        Initialize form with user instance.
        
        Args:
            user: User instance
            *args: Variable length argument list
            **kwargs: Arbitrary keyword arguments
        N)r[   r7   r8   )r<   r[   r=   r>   r?   r4   r5   r8   d  s   	zPasswordChangeForm.__init__c                 C   s,   | j d}|r| j|sttd|S )z
        Validate current password.
        
        Returns:
            str: Current password
            
        Raises:
            ValidationError: If current password is incorrect
        current_passwordzCurrent password is incorrect.N)rC   rD   r[   check_passwordr   r:   )r<   r   r4   r4   r5   clean_current_passwordp  s   
z)PasswordChangeForm.clean_current_passwordc                 C   s4   | j d}|rt|| j t|sttd|S )zi
        Validate new password strength.
        
        Returns:
            str: New password
        new_password1rW   N)rC   rD   r   r[   r   r   r:   )r<   r   r4   r4   r5   clean_new_password1  s   z&PasswordChangeForm.clean_new_password1c                    s>   t   }|d}|d}|r|r||krttd|S )zj
        Validate password confirmation.
        
        Returns:
            dict: Cleaned data
        r   new_password2z#The two password fields must match.N)r7   cleanrD   r   r:   )r<   rC   r   r   r?   r4   r5   r     s   


zPasswordChangeForm.cleanc                 C   s&   | j d }| j| | j  | jS )zj
        Save the new password.
        
        Returns:
            User: Updated user instance
        r   N)rC   r[   set_passwordr]   )r<   passwordr4   r4   r5   r]     s   

zPasswordChangeForm.save)r/   r0   r1   rb   r   re   r:   PasswordInputr   r   r   r8   r   r   r   r]   ri   r4   r4   r?   r5   r   E  s8    r   )$rb   djangor   django.contrib.authr   django.contrib.auth.formsr   r   django.core.exceptionsr   django.utils.translationr   r:   'django.contrib.auth.password_validationr   django.core.validatorsr	   django.utils.htmlr
   rJ   modelsr   r   r   apps.authentication.utilsr   r   	ModelFormrk   rs   r   Formr   r   r   r   r4   r4   r4   r5   <module>   s,   
 r/M9!<%