a
    Ï[×i«.  ã                   @  s  d dl mZ d dlZd dlZd dlmZ d dlmZ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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" d dl#m$Z% d dl&m'Z'm(Z( d dl#m)Z* e
dgdZ+G dd„ deƒZ,G dd„ deƒZ-G dd„ deƒZ.G dd„ deƒZ/G dd„ deƒZ0G dd„ deƒZ1d\ddœd d!„Z2dd"d#œd$d%„Z3d&dd'd(œd)d*„Z4eeeeƒf Z5e+j6d+ee2ƒgd,dd-d.œd/d0„ƒZ7e+j6d1ee2ƒgd,d'dd-d2œd3d4„ƒZ8d5d6d7œd8d9„Z9e+ 6d:¡d'dd&d-d;œd<d=„ƒZ:e+j6d>ee2ƒgd,d'd-d?œd@dA„ƒZ;e+j6dBee2ƒgd,d'dd-dCœdDdE„ƒZ<e+j6dFee2ƒgd,d'dd-dCœdGdH„ƒZ=e+ 6dI¡d'dd&d-d;œdJdK„ƒZ>e+ ?dL¡d'd-d?œdMdN„ƒZ@e+ ?dO¡d'd-d?œdPdQ„ƒZAe+ ?dR¡edSdTdUfd-d'dVœdWdX„ƒZBe+ ?d1¡d'd-dYœdZd[„ƒZCdS )]é    )ÚannotationsN)Údatetime)Ú	AnnotatedÚAnyÚOptional)Ú	APIRouterÚDependsÚHeaderÚHTTPExceptionÚQueryÚRequestÚstatus)Ú	BaseModelÚField)Úselect)ÚAsyncSession)Úsettings)Úget_session)ÚPollÚ
PollStatusÚRoom)Úws)Úparticipants)Úas_utc_naiveÚutc_now)ÚvotingÚpolls)Útagsc                   @  s&   e Zd ZU dZded< dZded< dS )Ú
RoomCreateÚ ÚstrÚnameNúOptional[str]Úid)Ú__name__Ú
__module__Ú__qualname__r!   Ú__annotations__r#   © r(   r(   úGC:\Users\jasmi\Projects\line-hihaho-voting\backend\app\routers\polls.pyr      s   
r   c                   @  s|   e Zd ZU ded< eddZded< eedZded< eedZded	< ee	dZ
d
ed< ee	dZded< dZded< dS )Ú
PollCreater    Útitleé   )Ú
min_lengthz	list[str]Úoptions)Údefault_factoryÚtrigger_namesÚtrigger_keyszdict[str, Any]Úpause_actionzdict[str, dict[str, Any]]Úwinner_actionsr   ÚintÚduration_secondsN)r$   r%   r&   r'   r   r.   Úlistr0   r1   Údictr2   r3   r5   r(   r(   r(   r)   r*      s   
r*   c                   @  s>   e Zd ZU dZded< dZded< dZded< dZded	< dS )
ÚPollOpenBodyNzOptional[datetime]Údeadline_atr   r    Úopen_sourceÚopen_reasonúOptional[dict[str, Any]]Útrigger_event)r$   r%   r&   r9   r'   r:   r;   r=   r(   r(   r(   r)   r8   '   s   
r8   c                   @  s.   e Zd ZU ded< dZded< dZded< dS )	ÚPollOverrideBodyr    Úwinner_optionNr<   ÚactionTÚboolÚ
close_poll)r$   r%   r&   r'   r@   rB   r(   r(   r(   r)   r>   .   s   
r>   c                   @  s   e Zd ZU dZded< dS )ÚPollResendBodyNr<   r@   )r$   r%   r&   r@   r'   r(   r(   r(   r)   rC   4   s   
rC   c                   @  s"   e Zd ZU dZded< ded< dS )ÚVoteBodyNr"   Úvoter_idr    Úchoice)r$   r%   r&   rE   r'   r(   r(   r(   r)   rD   8   s   
rD   z4Annotated[Optional[str], Header(alias='X-Host-Key')]©Ú
x_host_keyc                 Ã  s&   t js
d S | t jkr"ttjdd‚d S )Núinvalid host key©Ústatus_codeÚdetail)r   Úhost_api_keyr
   r   ÚHTTP_403_FORBIDDENrG   r(   r(   r)   Úrequire_host_key=   s    
rO   rA   )ÚbodyÚreturnc                 C  sn   | j pd ¡  ¡ }| jpd ¡  ¡ }t| jtƒr6| jnd }t|pBi  d¡pLdƒ ¡ }|dkol| 	d¡olt
|ƒS )Nr   Ú
event_typeZplayerzhihaho_event:)r:   ÚstripÚlowerr;   Ú
isinstancer=   r7   r    ÚgetÚ
startswithrA   )rP   ÚsourceÚreasonÚtriggerrR   r(   r(   r)   Úallow_player_trigger_openD   s
    r[   r   r    )ÚrequestrP   rQ   c                 C  sB   | j  d¡}tjsdS |tjkr$dS t|ƒr0dS ttjdd‚d S )Nz
X-Host-KeyZno_host_key_configuredZhost_keyÚplayer_triggerrI   rJ   )ÚheadersrV   r   rM   r[   r
   r   rN   )r\   rP   rH   r(   r(   r)   Úensure_can_open_pollL   s    
r_   z/rooms)ÚdependenciesÚ
SessionDep)rP   Úsessionc                 Ã  sT   | j ptt ¡ ƒ}t ||| j¡I d H }| ¡ I d H  | |¡I d H  |j |jdœS )N)r#   r!   )	r#   r    ÚuuidÚuuid4Ú
voting_svcÚensure_roomr!   ÚcommitÚrefresh)rP   rb   ZridÚroomr(   r(   r)   Úcreate_roomZ   s
    rj   z/rooms/{room_id}/polls)Úroom_idrP   rb   c              	   Ã  sž   t  || ¡I d H  tt ¡ ƒ}t|| |jt |j	¡t
jd}t  ||j|j|j|j|jdœ¡ | |¡ | ¡ I d H  | |¡I d H  t | ¡I d H  t|ƒS )N)r#   rk   r+   Úoptions_jsonr   )r0   r1   r2   r3   r5   )re   rf   r    rc   rd   r   r+   ÚjsonÚdumpsr.   r   ÚdraftÚset_poll_configr0   r1   r2   r3   r5   Úaddrg   rh   Ú	ws_routerÚbroadcast_room_snapshotÚpoll_out)rk   rP   rb   ÚpidÚpollr(   r(   r)   Úcreate_pollc   s.    
ûûþ

rw   r   r7   )rv   rQ   c                 C  sJ   | j | j| jt | ¡| jj| j| j| j	r2| j	 
¡ nd t | ¡t | ¡dœ
S )N)
r#   rk   r+   r.   r   r?   Úwinner_sourcer9   ÚconfigÚruntime)r#   rk   r+   re   Úparse_optionsr   Úvaluer?   rx   r9   Ú	isoformatÚparse_poll_configÚparse_poll_runtime)rv   r(   r(   r)   rt      s    ört   z/polls/{poll_id}/open)Úpoll_idrP   r\   rb   c           	      Ã  sV  t ||ƒ}| t| ¡I d H }|s*tddƒ‚|jtjkr>t|ƒS |dkr\|jtjkr\tddƒ‚t	|j
ƒ}|r~|tƒ kr~tddƒ‚t |¡}tƒ  ¡ d |d	< |jp¢d
|d< |jp°d|d< ||d< |jd urÒ|j|d< t ||d ¡}|rî||d< t ||¡ tj|_||_
d |_d|_| |¡ | ¡ I d H  | |¡I d H  t |j¡I d H  t|ƒS )Né”  úpoll not foundr]   é™  z)player trigger can only open a draft pollé  z!deadline_at must be in the futureÚZZ	opened_atÚhostr:   Zmanual_openr;   Zopen_auth_modeZlast_open_eventÚcontroller_commandr   )r_   rV   r   r
   r   r   Úopenrt   ro   r   r9   r   re   r   r}   r:   r;   r=   Úbuild_open_pause_commandÚset_poll_runtimer?   rx   rq   rg   rh   rr   rs   rk   )	r€   rP   r\   rb   Z	auth_moderv   r9   rz   Zpause_commandr(   r(   r)   Ú	open_pollŽ   s>    








r‹   z/polls/{poll_id}/close)r€   rb   c                 Ã  sj   |  t| ¡I d H }|s tddƒ‚t ||¡I d H  | ¡ I d H  | |¡I d H  t |j	¡I d H  t
|ƒS ©Nr   r‚   )rV   r   r
   re   Úclose_poll_and_set_winnerrg   rh   rr   rs   rk   rt   ©r€   rb   rv   r(   r(   r)   rB   ±   s    
rB   z/polls/{poll_id}/override)r€   rP   rb   c                 Ã  s8  |  t| ¡I d H }|s tddƒ‚|j ¡ }|rF|t |¡vrFtddƒ‚|jrTtj	|_
|pZd |_d|_t |¡}tƒ  ¡ d |d< d|d	< d|d
< |jp¤t ||jd¡}t|tƒrêd|vrât |¡|jd|  d|¡tƒ  ¡ d dœ}||d< t ||¡ | |¡ | ¡ I d H  | |¡I d H  t |j¡I d H  t|ƒS )Nr   r‚   r„   z)winner_option must be one of poll optionsZhost_overrider…   Zoverride_atr†   Zoverride_sourceÚclose_reasonÚseqr@   ©r   r?   rX   r@   Ú	issued_atr‡   )rV   r   r
   r?   rS   re   r{   rB   r   Úclosedr   rx   r   r   r}   r@   Úbuild_winner_commandrU   r7   Únext_command_seqrŠ   rq   rg   rh   rr   rs   rk   rt   )r€   rP   rb   rv   Úwinnerrz   Úcommandr(   r(   r)   Úoverride_poll_winner½   s<    






û
r˜   z/polls/{poll_id}/control/resendc                 Ã  sì   |  t| ¡I d H }|s tddƒ‚t |¡}|  d¡p6i }|jpF|  d¡}t|tƒrV|s`tddƒ‚t |¡|j	d|t
ƒ  ¡ d d	œ|d< t
ƒ  ¡ d |d
< t ||¡ | |¡ | ¡ I d H  | |¡I d H  t |j¡I d H  dt|ƒdœS )Nr   r‚   r‡   r@   r„   zno action available to resendZhost_resendr…   r‘   Zlast_resend_atT)Úokrv   )rV   r   r
   re   r   r@   rU   r7   r•   r?   r   r}   rŠ   rq   rg   rh   rr   rs   rk   rt   )r€   rP   rb   rv   rz   Zcurrent_commandr@   r(   r(   r)   Úresend_control_commandá   s*    


û

rš   z/polls/{poll_id}/votesc              
   Ã  s  |  t| ¡I d H }|s tddƒ‚|jp(d ¡ }|j  d¡}t ||¡I d H }|rz|j|jkrz|rt||j	krttddƒ‚|j	}|sˆtddƒ‚zt
 ||||j¡I d H }W nH tyì }	 z0t|	ƒ}
|
d	krÎtdd
ƒ‚tddƒ‚W Y d }	~	n
d }	~	0 0 | ¡ I d H  t |j¡I d H  d| |jdœS )Nr   r‚   r   Ú
session_idi“  zvoter_id mismatch with sessionr„   zvoter_id is requiredÚinvalid_choicezinvalid choicerƒ   z poll not open or deadline passedT)r™   r€   rF   )rV   r   r
   rE   rS   ÚcookiesÚparticipants_svcÚget_session_recordrk   Úparticipant_idre   Ú	cast_voterF   Ú
ValueErrorr    rg   rr   rs   )r€   rP   r\   rb   rv   rE   ZsidZsid_recÚvÚeÚcoder(   r(   r)   Ú	post_voteû   s,    



 r¦   z/polls/{poll_id}c                 Ã  s(   |  t| ¡I d H }|s tddƒ‚t|ƒS rŒ   )rV   r   r
   rt   rŽ   r(   r(   r)   Úget_poll  s    
r§   z/polls/{poll_id}/statsc           	      Ã  s˜   |  t| ¡I d H }|s tddƒ‚t || ¡I d H }t |¡}|D ]}| |d¡ q@t| ¡ ƒ}t 	||¡\}}| |j
j|||||j
tjkr|jnd dœS )Nr   r‚   r   )r€   r   ÚcountsÚtotalZleaderÚtier?   )rV   r   r
   re   Úcompute_tallyr{   Ú
setdefaultÚsumÚvaluesÚpick_winnerr   r|   r   r“   r?   )	r€   rb   rv   ÚtallyÚoptsÚor©   r–   rª   r(   r(   r)   Ú
poll_stats  s"    

ùr³   z/polls/current.zroom id)Údescription)rb   rk   c                 Ã  sH   |   ttƒ tj|ktjtjk¡¡I d H }| ¡ }|s@t	ddƒ‚t
|ƒS )Nr   zno open poll for room)Úexecr   r   Úwhererk   r   r   rˆ   Úfirstr
   rt   )rb   rk   Úresultrv   r(   r(   r)   Úcurrent_poll3  s    ÿ

r¹   )rk   rb   c                 Ã  s6   |  ttƒ tj| k¡¡I d H }| ¡ }dd„ |D ƒS )Nc                 S  s   g | ]}t |ƒ‘qS r(   )rt   )Ú.0Úpr(   r(   r)   Ú
<listcomp>B  ó    zlist_polls.<locals>.<listcomp>)rµ   r   r   r¶   rk   Úall)rk   rb   r¸   r   r(   r(   r)   Ú
list_polls>  s     r¿   )N)DÚ
__future__r   rm   rc   r   Útypingr   r   r   Úfastapir   r   r	   r
   r   r   r   Úpydanticr   r   Úsqlmodelr   Úsqlmodel.ext.asyncio.sessionr   Ú
app.configr   Úapp.dbr   Úapp.models.entitiesr   r   r   Úapp.routersr   rr   Úapp.servicesr   rž   Úapp.services.time_utilsr   r   r   re   Úrouterr   r*   r8   r>   rC   rD   rO   r[   r_   ra   Úpostrj   rw   rt   r‹   rB   r˜   rš   r¦   rV   r§   r³   r¹   r¿   r(   r(   r(   r)   Ú<module>   sb   $
"#
