a
    AWe                     @   sH   d dl Z d dlmZ d dlmZmZmZmZmZmZ G dd deZ	dS )    N)datetime)DynamicDocumentDateTimeFieldBooleanField	ListFieldStringFieldDynamicFieldc                       s   e Zd ZdZeee dddZe	eddddd	Z
ed
ddZeejdddZeddddZedddZdddgdgdZ fddZdd Zdd Zdd Zdd Zdd  Zd!d" Zed#d$ Z  ZS )%Basear  
    Base class for MongoDB models with common fields and methods.
    
    This base class provides common fields and methods for MongoDB models, including fields for tags, soft deletion, and timestamps. It also supports additional custom fields through the use of a DynamicField.

    Attributes:
        public_id (str): A unique identifier for the document. It's automatically generated using UUID4.
        tags (list of str): A list of tags associated with the document.
        deleted (bool): A flag indicating whether the document has been 'soft deleted.'
        created_at (datetime): Date and time of creation.
        updated_at (datetime): Date and time of the last update.
        deleted_at (datetime): Date and time of deletion, if applicable. 

    Indexes:
        - public_id: A unique index on the public_id field, facilitating fast lookups by the unique identifier.
        - created_at: An index for sorting documents by creation date.

    Methods:
        - save(): Custom save method to update 'updated_at' field before saving.
        - archive(): Soft delete the document by setting the 'deleted' flag and timestamp.
        - restore(): Restore a soft-deleted document.
        - add_tag(tag): Add a tag to the document if it's not already present.
        - remove_tag(tag): Remove a tag from the document if it exists.
        - to_dict(): Convert the document to a dictionary with formatted datetime fields.
        - _format_datetime(dt): Helper method to format a datetime object to ISO 8601 string.
        - get_paginated(page, per_page): Get a paginated list of documents.

    Example:
        To create a new document with tags and save it:
        >>> new_doc = Base(tags=['tag1', 'tag2'])
        >>> new_doc.save()

    Example:
        To retrieve a paginated list of documents:
        >>> page = 1
        >>> per_page = 10
        >>> result = Base.get_paginated(page, per_page)
        >>> total = result['total']
        >>> items = result['items']

    Example:
        To add a custom field to a document:
        >>> document.extra_fields['custom_data'] = 'Some additional data'
        >>> document.save()
    Tz%A unique identifier for the document.)defaultunique	help_text   )
max_lengthZTagsz*List of tags associated with the document.)descriptionr   Fz?A flag indicating whether the document has been 'soft deleted.')r
   r   zDate and time of creation)r
   readonlyr   Nz Date and time of the last updatez(Date and time of deletion, if applicable	public_idz-created_at)allow_inheritanceabstractindexesorderingc                    s$   t  | _tt| j|i | dS )zP
        Custom save method to update 'updated_at' field before saving.
        N)r   utcnow
updated_atsuperr	   save)selfargskwargs	__class__ /app/app/models/base.pyr   C   s    
z	Base.savec                 C   s   d| _ t | _|   dS )zW
        Soft delete the document by setting the 'deleted' flag and timestamp.
        TN)deletedr   r   
deleted_atr   r   r   r   r    archiveJ   s    
zBase.archivec                 C   s   d| _ d| _|   dS )z2
        Restore a soft-deleted document.
        FN)r!   r"   r   r#   r   r   r    restoreR   s    zBase.restorec                 C   s"   || j vr| j | |   dS )zH
        Add a tag to the document if it's not already present.
        N)tagsappendr   r   tagr   r   r    add_tagZ   s    
zBase.add_tagc                 C   s"   || j v r| j | |   dS )z>
        Remove a tag from the document if it exists.
        N)r&   remover   r(   r   r   r    
remove_tagb   s    
zBase.remove_tagc                 C   sj   |    }t|d|d< | |d|d< | |d|d< | |d|d< |dd |S )z7
        Convert the document to a dictionary.
        _idid
created_atr   r"   _clsN)to_mongoto_dictstrpop_format_datetimeget)r   Zdocument_dictr   r   r    r2   j   s    zBase.to_dictc                 C   s   |rt |tr| S dS )zO
        Helper method to format a datetime object to ISO 8601 string.
        N)
isinstancer   	isoformat)r   dtr   r   r    r5   x   s    zBase._format_datetimec                 C   sb   t d|}tt d|d}| jdd }| jdd|d | |}|||dd |D dS )z4
        Get a paginated list of documents.
           d   F)r!   c                 S   s   g | ]}|  qS r   )r2   ).0docr   r   r    
<listcomp>       z&Base.get_paginated.<locals>.<listcomp>)totalpageper_pageitems)maxminobjectscountskiplimit)clsrA   rB   r@   	documentsr   r   r    get_paginated   s    
 zBase.get_paginated)__name__
__module____qualname____doc__r   r3   uuiduuid4r   r   r&   r   r!   r   r   r   r/   r   r"   metar   r$   r%   r*   r,   r2   r5   classmethodrL   __classcell__r   r   r   r    r	      s*   .r	   )
rQ   r   mongoenginer   r   r   r   r   r   r	   r   r   r   r    <module>   s    