o
    Ydh@K                     @   s   d 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mZ dd	lmZmZmZ dd
lmZ 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 Serializers Module

This module contains serializers for the accounts app to handle
API data serialization and deserialization for users, roles, and profiles.

Author: Senior Django Developer
Date: 2024
    )serializers)get_user_model)
Permission)gettext_lazy)ValidationError)datetime   )RoleUserProfile)is_password_strongc                       s.   e Zd ZdZG dd dZ fddZ  ZS )PermissionSerializerzw
    Serializer for Django permissions.
    
    Provides a clean representation of permissions for API responses.
    c                   @   s   e Zd ZeZdZdZdS )zPermissionSerializer.Meta)idnamecodenamecontent_typeN)__name__
__module____qualname__r   modelfieldsread_only_fields r   r   MC:\Users\vibe-look\OneDrive\Desktop\Adtlas_V\src\apps\accounts\serializers.pyMeta!   s    r   c                    s(   t  |}|jj|d< |jj|d< |S )z
        Custom representation to include content type information.
        
        Args:
            instance: Permission instance
            
        Returns:
            dict: Serialized permission data
        	app_labelr   N)superto_representationr   r   r   )selfinstancedata	__class__r   r   r   &   s   
z&PermissionSerializer.to_representation)r   r   r   __doc__r   r   __classcell__r   r   r!   r   r      s    r   c                   @   st   e Zd ZdZedddZe Zej	e
 ddeddZG dd dZd	d
 Zdd Zdd Zdd Zdd ZdS )RoleSerializerzo
    Serializer for Role model.
    
    Handles role data serialization with permissions and user counts.
    Tmany	read_onlyFz-List of permission IDs to assign to this rolechild
write_onlyrequired	help_textc                   @      e Zd ZeZdZdZdS )zRoleSerializer.Meta)r   r   descriptionpermissions
user_countpermission_ids
created_at
updated_at)r   r3   r4   N)r   r   r   r	   r   r   r   r   r   r   r   r   G       r   c                 C   s
   |j  S )z
        Get the number of users assigned to this role.
        
        Args:
            obj: Role instance
            
        Returns:
            int: Number of users with this role
        N)userscountr   objr   r   r   get_user_countO   s   

zRoleSerializer.get_user_countc                 C   J   |   }tjj|d}| jr|j| jjd}| r#t	
td|S )a  
        Validate role name uniqueness and format.
        
        Args:
            value: Role name value
            
        Returns:
            str: Validated role name
            
        Raises:
            ValidationError: If name is invalid
        r   pkz%A role with this name already exists.N)striptitler	   objectsfilterr   excluder>   existsr   r   _r   valuequerysetr   r   r   validate_name[   s   zRoleSerializer.validate_namec                 C   4   |rt jj|d}t|t|krttd|S )z
        Validate permission IDs exist.
        
        Args:
            value: List of permission IDs
            
        Returns:
            list: Validated permission IDs
        Zid__inz'One or more permission IDs are invalid.N)r   rA   rB   lenr   r   rE   )r   rG   Zexisting_permissionsr   r   r   validate_permission_idsw      
z&RoleSerializer.validate_permission_idsc                 C   s@   | dg }tjjdi |}|rtjj|d}|j| |S )z
        Create a new role with permissions.
        
        Args:
            validated_data: Validated role data
            
        Returns:
            Role: Created role instance
        r2   rK   Nr   )popr	   rA   creater   rB   r0   set)r   validated_datar2   roler0   r   r   r   rP      s   
zRoleSerializer.createc                 C   sX   | dd}| D ]
\}}t||| q
|  |dur*tjj|d}|j| |S )z
        Update role with new permissions.
        
        Args:
            instance: Role instance to update
            validated_data: Validated role data
            
        Returns:
            Role: Updated role instance
        r2   NrK   )	rO   itemssetattrsaver   rA   rB   r0   rQ   )r   r   rR   r2   attrrG   r0   r   r   r   update   s   zRoleSerializer.updateN)r   r   r   r#   r   r0   r   SerializerMethodFieldr1   	ListFieldIntegerFieldrE   r2   r   r:   rI   rM   rP   rX   r   r   r   r   r%   7   s     r%   c                   @   sN   e Zd ZdZe Ze ZG dd dZdd Z	dd Z
dd	 Zd
d ZdS )ProfileSerializerzY
    Serializer for Profile model.
    
    Handles user profile data serialization.
    c                   @   r.   )zProfileSerializer.Meta)phone_numberbiodate_of_birthavatar
avatar_urlager3   r4   )r3   r4   N)r   r   r   r   r   r   r   r   r   r   r   r      r5   r   c                 C   s0   |j r| jd}|r||j jS |j jS dS )z
        Get the full URL for the user's avatar.
        
        Args:
            obj: Profile instance
            
        Returns:
            str: Avatar URL or None
        requestN)r`   contextgetbuild_absolute_uriurl)r   r9   rc   r   r   r   get_avatar_url   s   
z ProfileSerializer.get_avatar_urlc                 C   sD   |j r t  }|j|j j }||j j|jdk r|d8 }|S dS )z
        Calculate user's age from date of birth.
        
        Args:
            obj: Profile instance
            
        Returns:
            int: User's age or None
        )yearr   N)r_   r   nowdateri   replace)r   r9   todayrb   r   r   r   get_age   s   
zProfileSerializer.get_agec                 C   s"   |rt |dkrttd|S )z
        Validate bio length and content.
        
        Args:
            value: Bio text
            
        Returns:
            str: Validated bio
        i  z#Bio must be 500 characters or less.N)rL   r   r   rE   r   rG   r   r   r   validate_bio   s
   
zProfileSerializer.validate_bioc                 C   s@   |r|j dkrttdg d}|j|vrttd|S )z
        Validate avatar file size and type.
        
        Args:
            value: Avatar file
            
        Returns:
            File: Validated avatar file
        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)sizer   r   rE   r   )r   rG   allowed_typesr   r   r   validate_avatar   s   


z!ProfileSerializer.validate_avatarN)r   r   r   r#   r   rY   ra   rb   r   rh   rn   rp   rs   r   r   r   r   r\      s    r\   c                   @   s   e Zd ZdZeddZedddZej	e
 ddeddZe Ze ZG dd	 d	Zd
d Zdd Zdd Zdd Zdd ZdS )UserSerializerze
    Serializer for User model.
    
    Handles user data serialization with profile and roles.
    T)r(   r&   Fz'List of role IDs to assign to this userr)   c                   @   s0   e Zd ZeZdZdZddiddiddidZdS )zUserSerializer.Meta)r   usernameemail
first_name	last_name	full_name	is_activeis_staffis_superuseris_verifieddate_joined
last_loginprofilerolesrole_ids	is_online)r   ru   r~   r   r   r,   Trv   rw   rx   N)r   r   r   r
   r   r   r   extra_kwargsr   r   r   r   r   )  s    
r   c                 C      |  S z
        Get user's full name.
        
        Args:
            obj: User instance
            
        Returns:
            str: User's full name
        Nget_full_namer8   r   r   r   r   :     
zUserSerializer.get_full_namec                 C   s:   |j rddlm} ddlm} |j | |dd kS dS )z
        Check if user is currently online.
        
        Args:
            obj: User instance
            
        Returns:
            bool: True if user is online
        r   )timezone)	timedelta   )minutesFN)r   django.utilsr   r   r   rj   )r   r9   r   r   r   r   r   get_is_onlineF  s
   zUserSerializer.get_is_onlinec                 C   r;   )z
        Validate email uniqueness.
        
        Args:
            value: Email address
            
        Returns:
            str: Validated email
        rv   r=   .A user with this email address already exists.N)lowerr?   r
   rA   rB   r   rC   r>   rD   r   r   rE   rF   r   r   r   validate_emailX  s   
zUserSerializer.validate_emailc                 C   rJ   )z
        Validate role IDs exist.
        
        Args:
            value: List of role IDs
            
        Returns:
            list: Validated role IDs
        rK   z!One or more role IDs are invalid.N)r	   rA   rB   rL   r   r   rE   )r   rG   Zexisting_rolesr   r   r   validate_role_idsp  rN   z UserSerializer.validate_role_idsc                 C   sj   | dd}| D ]
\}}t||| q
d|v r|d |_|  |dur3tjj|d}|j	| |S )z
        Update user with new roles.
        
        Args:
            instance: User instance to update
            validated_data: Validated user data
            
        Returns:
            User: Updated user instance
        r   Nrv   rK   )
rO   rT   rU   ru   rV   r	   rA   rB   r   rQ   )r   r   rR   r   rW   rG   r   r   r   r   rX     s   
zUserSerializer.updateN)r   r   r   r#   r\   r   r%   r   r   rZ   r[   rE   r   rY   ry   r   r   r   r   r   r   rX   r   r   r   r   rt     s$    
rt   c                   @   sx   e Zd ZdZejddeddZejdeddZejdded	d
Z	G dd dZ
dd Zdd Zdd Zdd ZdS )UserRegistrationSerializerzl
    Serializer for user registration via API.
    
    Handles user creation with password validation.
    T   z+Password must be at least 8 characters longr+   
min_lengthr-   zConfirm your passwordr+   r-   FzOptional phone number)r,   allow_blankr-   c                   @   s,   e Zd ZeZdZddiddiddidZdS )zUserRegistrationSerializer.Meta)rv   rw   rx   passwordpassword_confirmr]   r,   Tr   N)r   r   r   r
   r   r   r   r   r   r   r   r     s    
r   c                 C   s0   |   }tjj|d rttd|S )z
        Validate email uniqueness and format.
        
        Args:
            value: Email address
            
        Returns:
            str: Validated email
        r   r   N)	r   r?   r
   rA   rB   rD   r   r   rE   ro   r   r   r   r     s   
z)UserRegistrationSerializer.validate_emailc                 C      t |sttd|S )z
        Validate password strength.
        
        Args:
            value: Password
            
        Returns:
            str: Validated password
        gPassword must contain at least 8 characters with uppercase, lowercase, numbers, and special characters.Nr   r   r   rE   ro   r   r   r   validate_password  
   
z,UserRegistrationSerializer.validate_passwordc                 C   &   |d |d krt dtdi|S )
        Validate password confirmation.
        
        Args:
            attrs: Attribute dictionary
            
        Returns:
            dict: Validated attributes
        r   r   %Password confirmation does not match.Nr   r   rE   r   attrsr   r   r   validate  
   

z#UserRegistrationSerializer.validatec                 C   sn   | d | dd}tjj|d |d |d |d |d d}d	|_|  |r5tjj|d|id
\}}|S )z
        Create a new user with profile.
        
        Args:
            validated_data: Validated user data
            
        Returns:
            User: Created user instance
        r   r]    rv   rw   rx   r   )ru   rv   rw   rx   r   F)userdefaultsN)rO   r
   rA   create_userr}   rV   r   get_or_create)r   rR   r]   r   r   createdr   r   r   rP     s"   
	
z!UserRegistrationSerializer.createN)r   r   r   r#   r   	CharFieldrE   r   r   r]   r   r   r   r   rP   r   r   r   r   r     s*    r   c                   @   s>   e Zd ZdZe Ze ZG dd dZdd Z	dd Z
dS )	UserListSerializerzj
    Simplified serializer for user lists.
    
    Provides minimal user information for list views.
    c                   @   s   e Zd ZeZdZeZdS )zUserListSerializer.Meta)r   rv   rw   rx   ry   rz   r{   r}   r~   r   
role_namesN)r   r   r   r
   r   r   r   r   r   r   r   r   &  s    r   c                 C   r   r   r   r8   r   r   r   r   /  r   z UserListSerializer.get_full_namec                 C   s   dd |j  D S )z
        Get list of role names for the user.
        
        Args:
            obj: User instance
            
        Returns:
            list: List of role names
        c                 S   s   g | ]}|j qS r   r<   ).0rS   r   r   r   
<listcomp>E  s    z5UserListSerializer.get_role_names.<locals>.<listcomp>N)r   allr8   r   r   r   get_role_names;  s   
z!UserListSerializer.get_role_namesN)r   r   r   r#   r   rY   ry   r   r   r   r   r   r   r   r   r     s    	r   c                       sx   e Zd ZdZejdeddZejddeddZejdeddZ	 fd	d
Z
dd Zdd Zdd Zdd Z  ZS )PasswordChangeSerializerz\
    Serializer for password change via API.
    
    Handles secure password changing.
    TzYour current passwordr   r   zYour new passwordr   zConfirm your new passwordc                    s$   | dd| _t j|i | dS )z
        Initialize serializer with user context.
        
        Args:
            *args: Variable length argument list
            **kwargs: Arbitrary keyword arguments
        r   N)rO   r   r   __init__)r   argskwargsr!   r   r   r   ]  s   z!PasswordChangeSerializer.__init__c                 C   s$   | j r	| j |sttd|S )z
        Validate current password.
        
        Args:
            value: Current password
            
        Returns:
            str: Validated current password
        zCurrent password is incorrect.N)r   check_passwordr   r   rE   ro   r   r   r   validate_current_passwordh  s
   
z2PasswordChangeSerializer.validate_current_passwordc                 C   r   )z
        Validate new password strength.
        
        Args:
            value: New password
            
        Returns:
            str: Validated new password
        r   Nr   ro   r   r   r   validate_new_passwordx  r   z.PasswordChangeSerializer.validate_new_passwordc                 C   r   )r   new_passwordnew_password_confirmr   Nr   r   r   r   r   r     r   z!PasswordChangeSerializer.validatec                 C   s&   | j d }| j| | j  | jS )zj
        Save the new password.
        
        Returns:
            User: Updated user instance
        r   N)rR   r   set_passwordrV   )r   r   r   r   r   rV     s   

zPasswordChangeSerializer.save)r   r   r   r#   r   r   rE   current_passwordr   r   r   r   r   r   rV   r$   r   r   r!   r   r   H  s(    r   N)r#   rest_frameworkr   django.contrib.authr   django.contrib.auth.modelsr   django.utils.translationr   rE   django.core.exceptionsr   r   modelsr	   r
   r   apps.authentication.utilsr   ModelSerializerr   r%   r\   rt   r   r   
Serializerr   r   r   r   r   <module>   s$   
a {,