o
    ȟ1i4                     @   s   d dl Z d dlZd dlZd dlmZmZ d dlmZ d dl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 d dlmZ d dlmZm	Z	mZ d d	lmZ d d
lmZ d dlZG dd dZdS )    N)datetimetimezone)Path)settings)GenericError)EventEventParticipant	EventCartEventPaymentDiscountCouponParentParticipantWalletHistory)EventResponseSchema)get_dbr   	BASE_PATH)
joinedload)send_event_order_summary_emailc                   @   s   e Zd ZdZdd Zdd Zdd Zdefd	d
Zdd Z	dd Z
dd Z	 dd Zdd Zdd ZdefddZdefddZdefddZdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*efd+d,Zd-d. Zd/d0 Zd1S )2EventServiceZgbpc                    s   |j r?t|j jj}t  | }td|  }|j  I d H }t|d}|	| W d    |S 1 s8w   Y  |S d S )Nuploads/wb)
imager   filenamesuffixuuiduuid4r   readopenwrite)selfrequestfile_extensionnew_filenamefile_locationcontentf r&   /app/services/event.pyupload_image   s   
zEventService.upload_imagec                    s  |  |I d H }g }|jD ]E}|rNt|jj}t  | }td|  }| I d H }t	|d}	|	
| W d    n1 sCw   Y  || q|d  qt j}
zM|
  t|j|j|j|j|j|j|j|j|d	}|
| |
  |
| t|j|D ]\}}t|j||d}|
| q|
  |W W  d    S  ty } z|
  t ddt!| dd }~ww 1 sw   Y  d S )Nr   r   )	nameevent_start_dateevent_end_dateevent_start_timeevent_end_timepricedescriptionlocationr   event_idr)   r     zError creating event: status_codeexc)"r(   participant_imagesr   r   r   r   r   r   r   r   r   appendr   beginr   r)   r*   r+   r,   r-   r.   r/   r0   addcommitrefreshzipparticipant_namesr   id	Exceptionrollbackr   str)r   r    Zevent_imager7   r   r!   r"   r#   r$   r%   dbeventr)   db_participanter&   r&   r'   create_event   s^   


zEventService.create_eventc                 C   s   t  B}|ttjd  }g }|D ]%}t|	 }|t
t
j|jk }dd |D |d< || q|W  d    S 1 sHw   Y  d S )Nc                 S      g | ]}|j |j|jd qS r)   r   	image_urlrJ   .0pr&   r&   r'   
<listcomp>\       z0EventService.fetch_all_event.<locals>.<listcomp>participants)r   queryr   where
deleted_atis_allr   model_validate
model_dumpr   r2   r?   r8   )r   rC   recordseventsrecord
event_datarQ   r&   r&   r'   fetch_all_eventS   s    


$zEventService.fetch_all_eventr2   c                 C   s   t  A}|ttj|ktjd  }|stddd|t	t	j
|k }t| }dd |D |d< |W  d    S 1 sGw   Y  d S )N  Event not foundr4   c                 S   rH   rI   rJ   rL   r&   r&   r'   rO   o   rP   z4EventService.fetch_event_details.<locals>.<listcomp>rQ   )r   rR   r   rS   r?   rT   rU   firstr   r   r2   rV   r   rW   rX   )r   r2   rC   r[   rQ   r\   r&   r&   r'   fetch_event_detailsb   s&   


$z EventService.fetch_event_detailsc              	      s
  |j g dd}t|dr|jd ur| |I d H }||d< g }t|drt|jd urt|jD ]E}|rnt|jj}t	  | }t
d|  }| I d H }	t|d}
|
|	 W d    n1 scw   Y  || q.|d  q.t }|ttj|ktjd j|dd}t|d	r|jd urt|dr|jd u rd gt|j }|j}|}t|t|krtd
ddt||D ]#\}}|ttj|ktj|k }|st|||d}| | q|!  |dkrtd
ddW d    d S 1 sw   Y  d S )N)r?   r   r7   r>   )excluder   r7   r   r   fetchsynchronize_sessionr>     z+Participant names and images count mismatchr4   r1   r   zCould not update event)"rX   hasattrr   r(   r7   r   r   r   r   r   r   r   r   r   r8   r   rR   r   rS   r?   rT   rU   updater>   lenr   r=   r   filterr2   r)   r`   r:   r;   )r   r2   r    payloadr   r7   r!   r"   r#   r$   r%   rC   resultnamesimagesr)   Zexisting_participantrE   r&   r&   r'   update_eventt   sb   
"

"zEventService.update_eventc                 C   |   t  1}|ttj|ktjd  }|stdddt	
tj|_|  ddiW  d    S 1 s7w   Y  d S )Nr^   r_   r4   messagezEvent deleted successfully)r   rR   r   rS   r?   rT   rU   r`   r   r   nowr   utcr;   )r   r2   rC   rD   r&   r&   r'   delete_event   s   $$zEventService.delete_eventc                 C   s   t  7}|ttjd }|jr|tj|jk}|jr(|tj|jk}| }dd |D W  d    S 1 s=w   Y  d S )Nc                 S   s   g | ]	}t | qS r&   )r   rW   rX   )rM   r[   r&   r&   r'   rO      s    z-EventService.event_filter.<locals>.<listcomp>)	r   rR   r   rj   rT   rU   r*   r+   rV   )r   r    rC   rR   rY   r&   r&   r'   event_filter   s   $zEventService.event_filterc                    s   t  d}zG|  |ttj|jk }|s tddd|j	|j
 }t|j|d |d |j
|d}|| |  || |W W  d    S  tyg } z|  tddt| dd }~ww 1 skw   Y  d S )	Nr^   r_   r4   r?   	user_type)r2   user_idrv   no_of_participantstotal_amountr3   zError creating event cart: )r   r9   rR   r   rj   r?   r2   r`   r   r.   rx   r	   r:   r;   r<   r@   rA   rB   )r   r    userrC   rD   ry   
event_cartrF   r&   r&   r'   create_event_cart   s4   

zEventService.create_event_cartc                 C   sR   |j |j|j|j|j|j|j|j|j |j|j	|j
|j|j|j|j|j|jd
d	S )z>Generate response dictionary for event cart with event details)
r?   r)   r*   r+   r,   r-   r.   r/   r0   r   )	r?   r2   rw   rv   rx   ry   
created_at
updated_atrD   )r?   r2   rw   rv   rx   ry   r}   r~   r)   r*   r+   r,   r-   r.   r/   r0   r   )r   cartrD   r&   r&   r'   _generate_event_cart_response   s(   z*EventService._generate_event_cart_responsec              	      s   t  =}|ttttjtjktj|d ktj	|d ktj
d tj
d tjdk } fdd|D W  d    S 1 sCw   Y  d S )Nr?   rv   Fc                    s   g | ]
\}}  ||qS r&   )r   )rM   r   rD   r   r&   r'   rO     s    z:EventService.get_event_cart_by_user_id.<locals>.<listcomp>)r   rR   r	   r   joinr2   r?   rS   rw   rv   rT   rU   is_cart_processedrV   )r   rz   rC   datar&   r   r'   get_event_cart_by_user_id   s   


$z&EventService.get_event_cart_by_user_idevent_cart_idc                 C   s   t  :}|ttttjtjktj|ktj	d tj	d 
 }|s,tddd|\}}| ||W  d    S 1 s@w   Y  d S )Nr^   Event cart not foundr4   )r   rR   r	   r   r   r2   r?   rS   rT   rU   r`   r   r   )r   r   rC   rl   r   rD   r&   r&   r'   fetch_event_cart_details  s    


$z%EventService.fetch_event_cart_detailsc                    sx   t  .}|ttj|ktjd |jdd}|	  |dkr*t
dddW d    d S 1 s5w   Y  d S )NT)exclude_unsetr   rf   zCould not update event cartr4   )r   rR   r	   rS   r?   rT   rU   rh   rX   r;   r   )r   r   r    rC   rl   r&   r&   r'   update_event_cart  s   

"zEventService.update_event_cartc                 C   rp   )Nr^   r   r4   rq   zEvent cart deleted successfully)r   rR   r	   rS   r?   rT   rU   r`   r   r   rr   r   rs   r;   )r   r   rC   r   r&   r&   r'   delete_event_cart)  s   

$zEventService.delete_event_cartc                 C   s,  |rt  ,}|ttj|jktj|k }||jkr*t	|dfW  d    S W d    n1 s4w   Y  d}|j
r\t	||jkr[|jdkrVt	|t	|j d }nt	|j}n|jdkrmt	|t	|j d }nt	|j}t|dr|jrt|t	|j}t||}tdt	|| }t	||fS )Nr   
percentaged   max_discount)r   rR   r
   rj   discount_coupon_idr?   rw   countuses_per_customerfloat	rule_typemin_cart_valuediscount_typediscount_valuerg   r   minmax)r   Zcart_total_amountdiscount_coupon_instancerw   rC   Zusage_countZcalculated_discountr&   r&   r'   apply_discount5  s8   



	




zEventService.apply_discountc                 C   s   d}|j rVt F}|d dkr|t|d j}n+|d dkr>|ttj|d ktj	
d  j}W d    |S W d    |S W d    |S 1 sQw   Y  |S )Nr   rv   parentr?   participant)
use_walletr   rR   r   getwallet_amountr   rj   r?   	parent_idrU   r`   )r   r    rz   r   rC   r&   r&   r'   fetch_wallet_amountW  s*   



z EventService.fetch_wallet_amountc                    s
  d}d}d}d}d}d}t  }	z|d dkr*|	ttj|d k }
n|d dkr?|	ttj|d k }
|
sGtd	d
d|	t	t
tjtj|d ktj|d ktjdtjdk}| dkrutd	dd| }tdd |D }| |d }d}d}|jrt  }|	ttj|jktjdktjt  ktjt  ktjdk }|r| |||d \}}|j r||d d  }|j!r|d dkr|	tj"tj|d k# pd}n|d dkr|	tj"tj|d k# p
d}t$||}||8 }|dkr$| %|||}|j&}n
d}tt'j(}d}t)|d |d ||||dkr?dnd||||||d}|	*| |D ]	}||_+d|_qP|	,  |dkr|dkr|d dkr|	ttj|d k-tj"tj"| i n1|d dkr|	ttj|d k-tj"tj"| i |	*t.|j|j|j|d|j+dddd	 |	,  ||||t/0d d| t/0d d| ||dW W  d   S  t1y } z|	2  tddt3| dd}~ww 1 sw   Y  dS ) a  
        Creates a payment session for event cart items.
        
        Args:
            request: Payment request containing discount_coupon_code and charity flag
            user: Dictionary containing user id and user_type
            
        Returns:
            Dictionary containing payment_url, status, transaction details
            
        Raises:
            GenericError: If cart is empty or payment creation fails
        NpendingFr   rv   r   r?   r   r^   zUser not foundr4   zEvent cart is emptyc                 S   s   g | ]}|j qS r&   )ry   rM   r   r&   r&   r'   rO     s    z=EventService.create_event_payment_session.<locals>.<listcomp>T   r   successstripewallet)rw   rv   
stripe_urlry   payment_statuspayment_methodpaid_onis_payment_completedtransaction_batch_idcoupon_discounted_amountr   used_wallet_amountpurchaseN/APurchased event(s)	event_payment_idrv   refund_for_idamountrefund_typetransaction_idnote	is_creditrq   
APP_UI_URL/dashboard/event-success//dashboard/event-failed/)Zpayment_urlr   r   r   success_url
cancel_urlr   r   rf   z(Could not create event payment session: )4r   rR   r   rj   r?   r`   r   r   r	   optionsr   rD   rw   rv   rT   rU   r   r   rV   sum_generate_transaction_iddiscount_coupon_coder   rr   dater   codestatus
start_dateend_dateis_applicable_for_eventr   charityr   r   scalarr   _generate_event_payment_linkurlr   rs   r
   r:   r   r;   rh   r   osgetenvr@   rA   rB   )r   r    rz   Zsession_urlr   r   r   r   r   rC   Zuser_existsevent_cartsry   r   r   Zcalculated_coupon_discountcurrent_dater   sessionpaymentr   rF   r&   r&   r'   create_event_payment_sessionb  s   
 

	

&&



 
 z)EventService.create_event_payment_sessionc                 C   s0   t t d }t|dd }| d| dS )z
        Generates a unique transaction ID for payment tracking.
        
        Args:
            user_id: ID of the user making the payment
            
        Returns:
            String containing timestamp, user_id and event identifier
        i  iN-z-evnt)inttimerB   )r   rw   	timestampZbase_idr&   r&   r'   r     s   
z%EventService._generate_transaction_idc              	   C   s   d dd |D }d| jt|d dd| dd	d
g}tjt_tjjj	dg|dd|it
d d| t
d d| d}|jrmtj d}tj }d}	|D ]}
|
j|kr`d}	 nqUt|	 |	sm| t| |S )ai  
        Creates a Stripe checkout session for event payments.
        
        Args:
            event_carts: List of EventCart objects
            total_amount: Total payment amount in currency units
            transaction_batch_id: Unique transaction identifier
            
        Returns:
            Stripe Session object containing payment URL
        ,c                 S   s   g | ]}|j jqS r&   )rD   r)   r   r&   r&   r'   rO     s    z=EventService._generate_event_payment_link.<locals>.<listcomp>   r   zWAC Event Purchasez
Event(s): )r)   r/   )currencyZunit_amountZproduct_data)ZquantityZ
price_dataZcardr   r   r   r   r   )Zpayment_method_types
line_itemsmodemetadatar   r   z/event/stripe/webhookFT)r   r   r   r   stripe_secret_keyr   api_keycheckoutSessioncreater   r   r   stripe_webhook_urlWebhookEndpointlistprintcreate_webhook)r   r   ry   r   r/   r   r   webhook_urlZexisting_webhooksZis_webhook_existswebhookr&   r&   r'   r     s@   


z)EventService._generate_event_payment_linkc                 C   s    t d |jj|g dd}|S )Nzcreating webhook)zpayment_intent.succeededcheckout.session.completedzpayment_intent.payment_failed)r   Zenabled_events)r   r   r   )r   r   r   r   r&   r&   r'   r   D  s   zEventService.create_webhookrk   c                 C   sB  t  }t|d}|d dkr|d d d d }t| |d d d d	kr|ttj|d d d d k	 }|sIt
d
dd|jr|jdkr|jdkro|ttj|jk	 }|rn| j|j8  _n|jdkr|ttj|jk	 }|r| j|j8  _|ttj|kjd|d d d dt ddd |ttj|kddi |ttj|ktjdk	 }|rt|j |jr|jdkr|t|j|j|j|jd|jdddd	 n|ttj|kjddddd |  W d   dS W d   dS 1 sw   Y  dS )a  
        Updates payment status and handles wallet deduction if payment was completed using wallet.
        
        Args:
            payload: Payment payload containing transaction details
            
        Returns:
            Updated payment record
        zutf-8typer   r   objectr   r   r   Zpaidr^   zPayment not foundr4   r   r   r   r   Zpayment_intentT)r   
payment_idr   r   rc   rd   r   r   r   Fr   r   Zfailed)r   r   N)r   jsonloadsdecoder   rR   r
   rj   r   r`   r   r   rv   r   r?   rw   r   r   rh   r   rr   r	   r   r   r:   r   r;   )r   rk   rC   rD   r   r   r   r   r&   r&   r'   update_paymentO  s   




	


$zEventService.update_paymentc           
      C   sL  t  }|t }g }|D ]}|tttjtjk	tj
|j
ktjdk }|D ]d}i }|jdkrP|t	tj|jk }|rO|j|j|jd}n|jdkrn|t	tj|jk }	|	rn|	j|	j|	jd}||j|j
d||j|jj|jj|j|j|j|j|j|jd	 q-q|W  d   S 1 sw   Y  dS )z
        Retrieves all event bookings for admin view
        Returns:
            List[AdminEventBookingResponse]: List of booking details
        Tr   )
first_name	last_nameemailr   )r?   r   )	r2   
event_name
event_dateparticipants_country   r   payment_dater   discount_amountN)r   rR   r
   rV   r	   r   r   r2   r?   rj   r   r   rv   r   rw   r`   r   r   r   r   r8   rD   r)   r*   rx   ry   r   r   r   r   )
r   rC   paymentsrl   r   cartsr   Zuser_detailsr   r   r&   r&   r'   get_all_event_bookings  sb   



%$z#EventService.get_all_event_bookingsc                 C   s   t  e}|ttj|d ktj|d k }g }|D ]A}|tt	tj
t	jktj|jktjdk }|D ]"}||j|j
|jj|jj|j|j|j|j|j|j|j|jd q;q|W  d   S 1 skw   Y  dS )z
        Retrieves all event purchases for the current user.
        Returns:
            List[EventPurchaseDetailResponse]: List of purchase details
        r?   rv   T)r   r2   r   r   r   ry   r   r   r   r   r   r   N)r   rR   r
   rj   rw   rv   rV   r	   r   r   r2   r?   r   r   r8   rD   r)   r*   rx   ry   r   r   r   r   r   r   )r   rz   rC   r   rl   r   r   r   r&   r&   r'   get_user_event_purchases  sH   



$z%EventService.get_user_event_purchasesN)__name__
__module____qualname__r   r(   rG   r]   r   ra   ro   rt   ru   r|   r   r   r   r   r   r   r   r   r   r   r   rB   r   r   r   r&   r&   r&   r'   r      s4    5?

" #2O:r   )r   r   r   r   r   pathlibr   r   core.configr   core.security.exceptionsr   modelsr   r   r	   r
   r   r   r   r   schema.eventr   r   r   sqlalchemy.ormr   Zcore.utilityr   r   r   r&   r&   r&   r'   <module>   s    (