
    =h#                         d dl Z d dlZd dlmZmZ d dlmZmZmZm	Z	m
Z
mZmZ d dlmZ d dlmZmZmZ d dlmZmZ  ed      Z ed      Z G d	 d
eeeef         Zy)    N)ABCabstractmethod)GenericTypeVarListOptionalTypeUnionAny)Session)selectdeletefunc)DatabaseErrorNotFoundExceptionTDBModelc            	       ~   e Zd ZdZdedee   fdZddee	   dee	   de
e   fd	Zde	fd
Zdee	ef   dee   fdZdee	ef   dee   fdZddededee   ee   z  fdZdedefdZdee	ef   dedefdZdee	ef   defdZdedefdZdedefdZdededefdZedee   dee   fd       Zededefd       Zy)BaseRepositoryz
    Abstract base repository for handling database operations using SQLAlchemy.

    Provides generic methods for CRUD operations while ensuring proper error handling.
    
db_sessionmodel_classc                      || _         || _        y)z
        Initializes the repository with a database session and model class.

        :param db_session: SQLAlchemy database session.
        :param model_class: The SQLAlchemy model class associated with the repository.
        N)dbr   )selfr   r   s      J/var/www/html/phonemate/phone_mate_backend/repositories/base_repository.py__init__zBaseRepository.__init__   s     &    Nstartlimitreturnc                   K   	 t        | j                        }||j                  |      }||dkD  r|j                  |      }| j                  j                  |      }|j                         j                         }|D cg c]  }| j                  |       c}S c c}w # t        $ r2 t        j                  t        j                                t               w xY ww)aK  
        Retrieves all records of the given model with optional pagination.

        :param start: Offset for pagination.
        :param limit: Maximum number of records to retrieve.
        :return: List of Pydantic entities representing the database records.
        :raises DatabaseError: If a database operation fails.
        r   )r   r   offsetr   r   executescalarsall
_to_entity	Exceptionloggingerror	traceback
format_excr   )r   r   r   queryresult	db_modelsmodels          r   get_allzBaseRepository.get_all   s     	"4++,E U+ UQYE*WW__U+F(,,.I8AB	uDOOE*	BBB 	"MM)..01/!	"s/   CA=B! BB! CB! !;CCc                   K   	 t        t        j                               j                  | j                        }| j
                  j                  |      }|j                         S # t        $ r}t               |d}~ww xY ww)z
        Retrieves the total count of records in the table.

        :return: Total number of records.
        :raises DatabaseError: If a database operation fails.
        N)
r   r   countselect_fromr   r   r#   
scalar_oner'   r   )r   r,   r-   es       r   get_all_countzBaseRepository.get_all_count6   sf     	)4::<(44T5E5EFEWW__U+F$$&& 	)/q(	)s)   BA A% $B%	A>.A99A>>Bidc                 0  K   	 t        | j                        j                  | j                  j                  |k(        }| j                  j                  |      }|j                         }|r| j                  |      S dS # t        $ r t               w xY ww)z
        Retrieves a record by its ID.

        :param id: The unique identifier of the record.
        :return: The corresponding Pydantic entity, or None if not found.
        :raises DatabaseError: If a database operation fails.
        N)
r   r   wherer7   r   r#   scalar_one_or_noner&   r'   r   )r   r7   r,   r-   db_models        r   	get_by_idzBaseRepository.get_by_idD   s     	"4++,2243C3C3F3F"3LMEWW__U+F002H084??8,BdB 	"/!	"s)   BA8A? <B=A? >B?BBc                   K   	 t        | j                        j                  | j                  j                  |k(        }| j                  j                  |      }|j                         S # t        $ r}t               d}~ww xY ww)a  
        Retrieves a raw SQLAlchemy model by its ID without conversion.

        :param id: The unique identifier of the record.
        :return: The SQLAlchemy model instance, or None if not found.
        :raises DatabaseError: If a database operation fails.
        N)	r   r   r9   r7   r   r#   r:   r'   r   )r   r7   r,   r-   r5   s        r   get_by_id_rawzBaseRepository.get_by_id_rawT   so     	"4++,2243C3C3F3F"3LMEWW__U+F,,.. 	"/!	"s)   BA%A* )B*	B3
A==BB
field_namevaluec                   K   	 t        | j                  |      }t        | j                        j                  ||k(        }| j                  j                  |      }|j                         }|r|r| j                  |      S dS |r|S dS # t        $ r2 t        j                  t        j                                t               w xY ww)az  
        Retrieves a record by a specific field.

        :param field_name: The field to filter by.
        :param value: The value to match.
        :param convert_to_entity: True/False weather to convert db model to entity or not.
        :return: The corresponding Pydantic entity, or None if not found.
        :raises DatabaseError: If a database operation fails.
        N)getattrr   r   r9   r   r#   r:   r&   r'   r(   r)   r*   r+   r   )r   r?   r@   convert_to_entitycolumnr,   r-   r;   s           r   get_by_fieldzBaseRepository.get_by_fieldc   s     
	"T--z:F4++,226U?CEWW__U+F002H 4<tx0F$F'81T1 	"MM)..01/!	"sA   CA<B	  CB	 CB	 CB	 C	;CCentityc                   K   	 | j                  |      }| j                  |      }| j                  j                  |       | j                  j	                          | j                  j                  |       | j                  ||      S # t        $ rq}| j                  j                          t        j                  dt        |              t        j                  t        j                                t               d}~ww xY ww)z
        Creates a new record in the database.

        :param entity: The Pydantic entity to be saved.
        :return: The saved Pydantic entity.
        :raises DatabaseError: If a database operation fails.
        zError creating entity: N)before_save_to_db_modelr   addcommitrefresh
after_saver'   rollbackr(   r)   strr*   r+   r   )r   rF   r;   r5   s       r   createzBaseRepository.createy   s     	"%%f-F((0HGGKK!GGNNGGOOH%??6844 	"GGMM3CF8<=MM)..01/!		"s*   DBB D	DA,C==DDc                    K   	 t        | j                        j                  | j                  j                  |k(        }| j                  j                  |      }|j                         }|s
t               | j                  | j                  |            }|j                         D ]  \  }}t        |||        | j                  j                          | j                  j                  |       | j                  |      S # t        $ rq}	| j                  j!                          t#        j$                  dt'        |	              t#        j$                  t)        j*                                t               d}	~	ww xY ww)a,  
        Updates an existing record in the database.

        :param id: The unique identifier of the record to update.
        :param entity: The Pydantic entity with updated values.
        :return: The updated Pydantic entity.
        :raises DatabaseError: If a database operation fails.
        zError updating entity: N)r   r   r9   r7   r   r#   r:   r   _get_clean_attributesrI   itemssetattrrK   rL   r&   r'   rN   r(   r)   rO   r*   r+   )
r   r7   rF   r,   r-   r;   updated_fieldskeyr@   r5   s
             r   updatezBaseRepository.update   s#    	"4++,2243C3C3F3F"3LMEWW__U+F002H#o%!778I8I&8QRN,224
U#u- 5 GGNNGGOOH%??8,, 	"GGMM3CF8<=MM)..01/!		"s*   E>C<D  E>	E;
A,E66E;;E>c                   K   | j                  |      }|t        	 t        | j                        j	                  | j                  j
                  |k(        }| j                  j                  |       | j                  j                          y# t        $ r)}| j                  j                          t               d}~ww xY ww)a  
        Deletes a record by its ID.

        :param id: The unique identifier of the record to delete.
        :raises DatabaseError: If a database operation fails.
        :raises NotFoundException: If a model class record not found against that id.
        NT)r<   r   r   r   r9   r7   r   r#   rK   r'   rN   r   )r   r7   r   r,   r5   s        r   r   zBaseRepository.delete   s      nnR(##	"4++,2243C3C3F3F"3LMEGGOOE"GGNN 	"GG/!	"s)   CA0B C	C $B;;C  Cr;   c                     |j                   j                         D ci c]  \  }}|j                  d      s|| c}}S c c}}w )z
        Removes private and SQLAlchemy-specific fields from a model before an update.

        :param db_model: The SQLAlchemy model instance.
        :return: A dictionary of cleaned attributes.
        _)__dict__rS   
startswith)r   r;   rV   r@   s       r   rR   z$BaseRepository._get_clean_attributes   sL     *2):):)@)@)B
)B:3>>#& J)B
 	
 
s   A c                     |S )z
        Hook method for preprocessing an entity before saving.

        Override in subclasses to implement custom logic.

        :param entity: The Pydantic entity before saving.
        :return: The processed entity.
         r   rF   s     r   rH   zBaseRepository.before_save   s	     r   c                 $    | j                  |      S )a!  
        Hook method for post-processing an entity after saving.

        Override in subclasses to implement custom logic.

        :param entity: The Pydantic entity before saving.
        :param db_model: The saved SQLAlchemy model.
        :return: The final processed entity.
        )r&   )r   rF   r;   s      r   rM   zBaseRepository.after_save   s     x((r   c                      y)z
        Converts a database model instance into a Pydantic entity.

        :param db_model: The SQLAlchemy model instance.
        :return: The corresponding Pydantic entity.
        Nr^   )r   r;   s     r   r&   zBaseRepository._to_entity        	r   c                      y)z
        Converts a Pydantic entity into a database model.

        :param entity: The Pydantic entity.
        :return: The corresponding SQLAlchemy model instance.
        Nr^   r_   s     r   rI   zBaseRepository._to_db_model   rb   r   )NN)T)__name__
__module____qualname____doc__r   r	   r   r   r   intr   r   r0   r6   r
   rO   r<   r>   r   rE   rP   rW   boolr   dictrR   rH   rM   r   r&   rI   r^   r   r   r   r      s   '7 'g '"8C= " "Y]^_Y` ".)S )"%S/ "hqk " "eCHo "(7:K ""S " "YabcYdgopwgxYx ","1 " "*"uS#X " "a "<"uS#X "4 "*

g 

$ 

	! 	 	
) 
)g 
)! 
) 8G#4 !   1   r   r   )r(   r*   abcr   r   typingr   r   r   r   r	   r
   r   sqlalchemy.ormr   
sqlalchemyr   r   r   utils.exceptionsr   r   r   r   r   r^   r   r   <module>rp      sO      # E E E " + + =CL
)
hS'!W*- hr   