
    feiB                        d Z ddlZddlmZmZmZ ddlmZmZmZm	Z	 ddl
mZmZ ddlmZmZ ddlmZmZ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mZmZm Z m!Z!m"Z"m#Z#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l0m1Z1 ddl2m3Z3 ddl4m5Z5 ddl6m7Z7 ddl8m9Z9 dedede:dee   fdZ;	 	 	 d3dede<de:de:deded ee:   d!ee:   d"ee:   dee   fd#Z=dede<de<fd$Z>dede:de?fd%Z@dede<fd&ZA	 	 d4ded'ed ee:   d!ee:   deee   e:f   f
d(ZBded)edeee   e:f   fd*ZCdededee   fd+ZDdeEfd,ZFdeEfd-ZGded.ede#fd/ZHded0edeee    e:f   fd1ZId5dedee<   dee!e:f   fd2ZJy)6zE
Authentication controller for handling auth-related business logic.
    N)datetime	timedeltatimezone)DictOptionalTupleUnion)HTTPExceptionstatus)Session
joinedload)selectand_update)EmailStr)User)AuthSession)
LoginRequestSchemaLoginResponseSchemaRegisterRequestSchemaRegisterResponseSchemaRefreshTokenRequestSchemaAuthTokenSchemaLogoutResponseSchemaUserProfileSchemaUserMeResponseSchemaUserMeDataSchema)UserCreateSchema
UserSchema)MerchantSchema)AddressSchema)create_user)jwt_manager)verify_password)settings)MerchantUsers)Merchant)Addressdbemailpasswordreturnc                 R   t        t              j                  t        j                  |k(        }t	        t        d      r.|j                  t        j
                  j                  d            }| j                  |      j                         }|syt        ||j                        sy|S )z
    Authenticate user by email and password.
    
    Args:
        db: Database session
        email: User's email address
        password: Plain text password
        
    Returns:
        User model if authentication successful, None otherwise
    
deleted_atN)r   r   wherer*   hasattrr.   is_executescalar_one_or_noner$   hashed_password)r)   r*   r+   stmtusers        F/var/www/html/hwPaymentPortal-be-uat/backend/src/apps/auth/services.pyauthenticate_userr8   '   s     $<djjE12Dt\"zz$//--d34::d..0D 8T%9%9:K    user_idaccess_tokenrefresh_tokenaccess_token_expires_atrefresh_token_expires_at
ip_address
user_agentdevice_infoc	                     	 t        ||||||||dd
      }	| j                  |	       | j                          | j                  |	       |	S # t        $ r}
| j                          Y d}
~
yd}
~
ww xY w)z$Create a new authentication session.TF)
r:   r;   r<   r=   r>   r?   r@   rA   	is_active
is_revokedN)r   addcommitrefresh	Exceptionrollback)r)   r:   r;   r<   r=   r>   r?   r@   rA   auth_sessiones              r7   create_auth_sessionrL   C   st    "%'$;%=!!#
 	|
		


<  
s   AA 	A.A))A.c                    	 t        j                  t        j                        }t	        t
              j                  t        t
        j                  |k(  t
        j                  dk(  t
        j                  dk(              j                  dd||      }| j                  |      }| j                          |j                  S # t        $ r | j!                          Y yw xY w)z&Revoke all active sessions for a user.TFrC   rD   
revoked_at
updated_atr   )r   nowr   utcr   r   r/   r   r:   rC   rD   valuesr2   rF   rowcountrH   rI   )r)   r:   rQ   r5   results        r7   revoke_all_user_sessionsrV   g   s    ll8<<( ;U''72))T1**e3 V	   	" D!
		 
s   B>C CCc                    	 t        j                  t        j                        }t	        t
              j                  t        t
        j                  |k(  t
        j                  dk(  t
        j                  dk(              j                  dd||      }| j                  |      }| j                          |j                  dkD  S # t        $ r | j!                          Y yw xY w)z
    Revoke a specific session by access token.
    
    Args:
        db: Database session
        access_token: The access token to revoke
        
    Returns:
        True if session was revoked, False otherwise
    TFrN   r   )r   rQ   r   rR   r   r   r/   r   r;   rC   rD   rS   r2   rF   rT   rH   rI   )r)   r;   rQ   r5   rU   s        r7   revoke_session_by_tokenrX      s    ll8<<( ;U,,<))T1**e3 V	   	" D!
		"" 
s   CC C C c                    	 t        j                  t        j                        }t	        t
              j                  t        t
        j                  |k  t
        j                  dk(              j                  d|      }| j                  |      }| j                          |j                  S # t        $ r | j                          Y yw xY w)z)Clean up expired authentication sessions.TF)rC   rP   r   )r   rQ   r   rR   r   r   r/   r   r=   rC   rS   r2   rF   rT   rH   rI   )r)   rQ   r5   rU   s       r7   cleanup_expired_sessionsrZ      s    ll8<<( ;U77#=))T1 V   	 D!
		 
s   B*B- -C	C	
login_datac                    t        | |j                  |j                        }|sy|j                  sy|j                  |j                  t        |dd      |j                  |j                  t        |dd      |j                  |j                  t        |dd      d	}d	|i}d	|i}t        t        j                  
      }t        t        j                        }	t        j                  ||      }
t        j                   ||	      }t#        j$                  t&        j(                        |z   }t#        j$                  t&        j(                        |	z   }t+        | |j                  |
|||||       t#        j$                  t&        j(                        |_        | j/                          t1        d|j                  |j                  |j                  |j                  |
|dt        j                  dz  	      }|dfS )a  
    Login user with email and password.
    
    Args:
        db: Database session
        login_data: Login request data
        ip_address: Client IP address
        user_agent: Client user agent
        
    Returns:
        Tuple of login response and message
    )NzIncorrect email or password)NzInactive userusernameNphoneis_superuserF	r:   r*   r]   
first_name	last_namer^   rC   is_verifiedr_   r6   minutes)days)r)   r:   r;   r<   r=   r>   r?   r@   zAuthentication successfulbearer<   )	messager:   r*   rC   rc   r;   r<   
token_type
expires_inzLogin successful)r8   r*   r+   is_user_activeidgetattrra   rb   rC   rc   r   r%   jwt_expires_minutesjwt_refresh_expires_daysr#   create_access_tokencreate_refresh_tokenr   rQ   r   rR   rL   
last_loginrF   r   )r)   r[   r?   r@   r6   	user_data
token_datarefresh_token_dataaccess_token_expiresrefresh_token_expiresr;   r<   access_expires_atrefresh_expires_atlogin_responses                  r7   
login_userr|      s   & R!1!1:3F3FGD2$ 77D*d3oo^^w-^^''ne<
I 		J
 		
 %X-I-IJ%8+L+LM22:?STL445GI^_M !X\\25II!hll36KK!# 1!3	 ll8<<0DOIIK )+jj..$$!#//"4
N ---r9   register_datac           	      B   t        |j                  |j                  |j                  |j                  |j
                  dd      }t        | ||j                        \  }}|d|fS t        d|j                  |j                  |j                  |j                        }||fS )z
    Register a new user.
    
    Args:
        db: Database session
        register_data: Registration request data
        
    Returns:
        Tuple of registration response and message
    TF)r*   ra   middle_namerb   r^   rC   rc   NzRegistration successful)ri   r:   r*   rC   rc   )r   r*   ra   r   rb   r^   r"   r+   r   rm   rC   rc   )r)   r}   user_create_datar6   ri   register_responses         r7   register_userr   (  s     (!! ++!--))!!  $4m6L6LMMD'|W} /)jj..$$ g%%r9   c                    t        t              j                  t        j                  |k(        }t	        t        d      r.|j                  t        j
                  j                  d            }| j                  |      j                         S )z
    Get user by email address.
    
    Args:
        db: Database session
        email: User's email address
        
    Returns:
        User model if found, None otherwise
    r.   N)	r   r   r/   r*   r0   r.   r1   r2   r3   )r)   r*   r5   s      r7   get_user_by_emailr   S  s`     $<djjE12Dt\"zz$//--d34::d..00r9   c                 H    t        j                  |       j                         S )z0Helper to serialize address data using Pydantic.)r!   model_validate
model_dump)addrs    r7   _serialize_addressr   e  s    ''-88::r9   c                     i }| j                   r9| j                   D ]*  }|j                  dv s|j                  ||j                  <   , |xs ddddddS )z5Helper to extract merchant preferences from settings.)countrylanguager   date_formattime_formatUSen_USzAmerica/Denverz
MM/DD/YYYYz
HH:mm:ss A)r%   
field_namevalue)merchant_datapreferencessettings      r7   _get_merchant_preferencesr   j  sm    K$-- 	@G!!%ff29--G../	@  $## r9   r6   c                    t        t              j                  t        j                  |j                  k(        j                  t        j
                  dk(        }| j                  |      j                         }d}g }|rt        t              j                  t        j                  |j                  k(        j                  t        t        j                              }| j                  |      j                         }|rd| j                  t        t              j                  t        j                  |j                  k(              j                         j                         }g }|r| j                  t        t              j!                  t        t        j                  t        j                  k(        j                  t        j                  |j                  k(              j                         j                         }t#        j$                  |      }|j'                         }	|j(                  xs d|	d<   |r|j
                  nd|	d<   |D 
cg c]  }
t+        |
       c}
|	d<   i }|rt-        j$                  |      }|j'                         }d}|r!t/        d |D        |d	         }t+        |      }d}|j                  r6t0        j2                   d
|j                   d|j                  j4                   }|j7                  ||j8                  rd|j8                   dnd|t;        |      |j<                  xs dd       t?        tA        |	|      ddd      S c c}
w )z
    Get current user profile information with merchant details.
    
    Args:
        db: Database session
        user: Current authenticated user
        
    Returns:
        User profile with merchant data
    TN r   Fis_owner	addressesc              3   :   K   | ]  }|j                   s|  y wN)use_as_default).0r   s     r7   	<genexpr>z+get_current_user_profile.<locals>.<genexpr>  s      \$H[H[ \s   r   z)/api/v1/files/download?filepath=/uploads//zhttps://z.hubwallet.comactive)logo_urlactive_domaindefault_addressr   r   )r6   merchant   zCurrent user details)datastatus_codesuccessri   )!r   r&   r/   r:   rm   r   r2   r3   r'   merchant_idoptionsr   
brand_logor(   scalarsalljoinr   r   r   r   r   r    nextr%   API_BASE_URLnamer   	subdomainr   payrix_statusr   r   )r)   r6   merchant_user_stmtmerchant_userr   merchant_addressesmerchant_stmtuser_addressesuser_schema	user_dictr   merchant_dictmerchant_schemar   default_addrr   s                   r7   get_current_user_profiler   {  s    	}	}$$/	0	}%%-	. 
 JJ12EEGMM 8U8;;-";";;<WZ 3 345 	
 

=1DDF!#w%%g&9&9]=M=M&MN"gi 
 N7OT-!4!48Q8Q!QRU=((DGG34
 ')CCE	 	 ++D1K&&(I  $//52Im6CM22IjCQR406RIk M(77F'224  \2D \^pqr^stL0>O##"//00YZgZsZsYttu  wD  wO  wO  wT  wT  vU  VH 	 S`SjSjx(?(?'@Opt.4]C#11=X
 	  9}E&	 7 Ss   Mrefresh_requestc                 
   t        j                  |j                        }|sy|j                  d      dk7  ry|j                  d      }|sy|j                  d      }t	        t
              j                  t
        j                  |k(        }| j                  |      j                         }|r|j                  sy|j                  |j                  t        |dd	      |j                  |j                  t        |d
d	      |j                  |j                   t        |dd      d	}d|i}t#        t$        j&                        }	t        j(                  ||	      }
t+        |
|j                  dt$        j&                  dz        }|dfS )z
    Refresh access token using refresh token.
    
    Args:
        db: Database session
        refresh_request: Refresh token request data
        
    Returns:
        Tuple of new tokens and message
    )NzInvalid refresh tokentyperG   )NzInvalid token typer6   r:   )NzUser not found or inactiver]   Nr^   r_   Fr`   rd   rg   rh   )r;   r<   rj   rk   zToken refreshed successfully)r#   verify_tokenr<   getr   r   r/   rm   r2   r3   rl   r*   rn   ra   rb   rC   rc   r   r%   ro   rq   r   )r)   r   payloadrt   r:   	user_stmtr6   updated_user_dataru   rw   new_access_tokentoken_responses               r7   refresh_access_tokenr     sc    &&'D'DEG, {{6i')F#I,mmI&G t""477g#56I::i 335Dt**1 77D*d3oo^^w-^^''ne<
 	!J %X-I-IJ"66zCWX %%%33//"4	N 999r9   c                 L    d}|rt        | |      }t        d|      }|d| dfS )z
    Logout user by revoking session(s).
    
    Args:
        db: Database session
        user_id: User ID to revoke all sessions
        
    Returns:
        Tuple of logout response and message
    r   zLogout successful)ri   logged_out_sessionszLogged out z session(s))rV   r   )r)   r:   sessions_revokedlogout_responses       r7   logout_userr     sB     3B@*#,O
 k*:);;GGGr9   )NNN)NNr   )K__doc__uuidr   r   r   typingr   r   r   r	   fastapir
   r   sqlalchemy.ormr   r   
sqlalchemyr   r   r   pydantic.networksr   src.apps.users.models.userr   !src.apps.auth.models.auth_sessionr   !src.apps.auth.schemas.auth_commonr   r   r   r   r   r   r   r   r   r   "src.apps.users.schemas.user_commonr   r   *src.apps.merchants.schemas.merchant_commonr    src.apps.base.schemas.commonr!   src.apps.users.servicesr"   src.apps.auth.utils.jwtr#   src.core.utils.passwordr$   src.core.configr%   (src.apps.merchants.models.merchant_usersr&   "src.apps.merchants.models.merchantr'   src.apps.base.models.addressr(   strr8   intrL   rV   boolrX   rZ   r|   r   r   dictr   r   r   r   r    r9   r7   <module>r      s    2 2 / / ) . + + & + 9   L E 6 / / 3 $ B 7 0' ( c htn F !% $!%!!! ! 	!
 &! '! ! ! #! k!H 3 3 @& &s &t &R S @ !% $	X.X."X. X. 	X.
 8'(#-.X.v(&(&((& 8*+S01(&V1' 1( 1x~ 1$; ;
 "U U U9M Up@:@:.@: 8O$c)*@:FHG Hhsm HuEY[^E^?_ Hr9   