o
    jh?                     @  s^  d dl mZ 	 d dlmZmZmZ d dlZd dlZd dlZd dl	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mZmZmZ e
 Zed	Zd.ddZejdededded dfd/ddZ ejdededdeddeddddfd0d!d"Z!d1d$d%Z"d2d&d'Z#ejd(eded d dded d ddeddd)dfd3d,d-Z$dS )4    )annotations)DictListTupleN)	APIRouterRequestQuery)HTMLResponseJSONResponse)	templatessb   )MOTIE_ORDER_POS_norm_normalize_position_normalize_department_canon_department
_pick_bestzgov.motie.heads_testposstrreturnc                 C  sH   t | }tdd|}tdd|}tdd|}tdd| }|S )Nz\(.*?\) u   (직무대리|대행|겸임)u   ^제\s*([0-9]+차관)$z\1z\s+ )r   resubstrip)r   p r   7/var/www/html/bot/app/web/pages/gov/motie/heads_test.pyr      s   r   z/gov/motie/heads_test)response_classr   )defaultrequestr   qdebugintc           +        s  zt ddjdddd jpg }W n ty#   g }Y nw |rg }t|	 }|D ]>}|
d|
dp<d	|
d
pBd|
d|
dpLd|
dpRdd}ddd | D 	 }|ri||v rn|| q0td| d||ddt| gg dS zt ddd jpg }	W n ty }
 ztd|
 g }	W Y d }
~
nd }
~
ww g d`fdd }|d!t|	  g }t|	D ]t\}}|
d"pd#}|
dpd#}t|}t|}t|
d
pd#}t|
dpd#}t|
dpd#}|||||||d$}|| d%kr>||kp||k}|s$d&kr>|d'| d(| d)| d*| d)| d+| d,| d- qi }i }i }|D ]4}|d" }|d }|rb|rb|||fg | |rn||g | |rz||g | qG|d.t|  t|	 }g }g }dad3d4 d5gd6gd7gd8}tD ]\}}}t|t||
fg }t|}|r|d
 pd}|d pɈ}|d pd}|d pd}d9kr|d:| d; d< d=| d>| d?t| d@ d&krt|D ]\} }!|dA|  dB|!d
  dC|!d  d>|!d  d-	 qnzd%kr|
g }"|dD dEt|" dF t|"d dG D ]\} }#|dH|  dB|#
d
 dC|#
d d>|#
d d-	 q>|
g }$|dI dJt|$  t|$d dG D ]\} }#|dK|  dL|#
d" dM|#
d
 dC|#
d d-	 qx fdNd| D }%|%rt|%}|d
 pd}|d p}|d pd}|d pd}d9kr|dO| dP dQ dR| dC| dSt|% d@ nt|
g hB  fdTd| D }&|&rGt|&}|d
 pd}|d p}|d pd}|d p!d}d9krF|dU| dV dQ dR| dP|
d" dC| dWt|& d@ nQdddf\}}}}|f d9krtdXdY | D }'tdZdY | D }(tj|'d&d[d\})tj|(d&d[d\}*|d]| d; d< d^|) d_|* 
 ||||||d}|r|d|||||g	 v r|| qtd| d|||dS )bNmotie_heads_curz(unit,position,name,phone,task,indent,ordordFdesc  unitindentr   nameu   (공석)positionphone-task)r*   r+   r,   r-   r.   r0   r   c                 S  s   g | ]}t |pd qS )r   )r   ).0xr   r   r   
<listcomp>G   s    z0gov_motie_heads_ordered_test.<locals>.<listcomp>zgov/motie/heads_test.htmlu(   산업통상자원부(MOTIE) - 테스트z![info] using motie_heads_cur viewz[info] rows=)r!   ministryr"   itemsr#   	dbg_linesmissesmotie_org_cur#department,position,name,phone,taskP  z&[heads_test] Supabase fetch failed: %smsgr   c                   s$     |  dkrt|  d S d S )Nr   )appendlogr#   )r;   )r6   r#   r   r   _dbgi   s   
z*gov_motie_heads_ordered_test.<locals>._dbgz[heads_test] fetched_rows=
departmentr   )department_rawr?   position_rawr-   r,   r.   r0         z[normalize#z] dep:'u   '→'z', pos:'z	', name:'z
', phone:''z[heads_test] unique_keys=expectedactualr   boolc                 S  st   t | }t |}||krdS |dkr(|dks |ds |dr"dS d|v r(dS |r8|r8||v r8t|dkr8dS dS )NT	   대변인u   부대변인FrB   )r   endswith
startswithlen)rE   rF   ear   r   r   _pos_matches   s   z2gov_motie_heads_ordered_test.<locals>._pos_matchesu   대변인실u   제1차관실u   제2차관실)rH   
   제1차관
   제2차관r   z[match] OK unit='z	', key=('z','z'), picked='z
', phone='z	' (cands=)u     └ cand[z] name='z', pos='z[debug] dep='z' has z rows
   z	    cand[z[debug] pos='z' bucket size=z    pos_cand[z] dep='z	', name='c                   s>   g | ]\\}}}|kr|D ]} | d pdr|qqS r-   r   getr1   dr   arrr)rN   dep_normpos_normr   r   r3         > z[match] FALLBACK unit='z', dep='z', expected_pos='z' -> picked='z' (loose_cands=c                   s>   g | ]\\}}}|v r|D ]} | d pdr|qqS rS   rT   rV   )rN   allowedr[   r   r   r3      r\   z[match] FALLBACK2 unit='z	', dep~='z' (loose2_cands=c                 S  s   h | ]\}}|qS r   r   )r1   rW   _r   r   r   	<setcomp>       z/gov_motie_heads_ordered_test.<locals>.<setcomp>c                 S  s   h | ]\}}|qS r   r   )r1   r^   r   r   r   r   r_      r`   g333333?)ncutoffz[match] MISS unit='z') near_dep=z
 near_pos=)r;   r   )rE   r   rF   r   r   rG   )r   tableselectorderlimitexecutedata	Exceptionr   lowerrU   joinvaluesr<   r   TemplateResponserK   r=   	exception	enumerater   r   
setdefault_MOTIE_ORDER_POSr   r5   setlistkeysdifflibget_close_matches)+r!   r"   r#   vr5   keyrY   rowhayrowsrL   r>   	norm_rowsidep_rawpos_rawdepr   r,   r.   r0   recchangedby_keyby_depby_posr7   _DEPT_EQUIVr*   r+   expected_poscandsjcrows_for_deprr
pos_bucketlooseloose2dep_keyspos_keysnear_depnear_posr   )rN   r]   r6   r#   rZ   r[   r   gov_motie_heads_ordered_test(   sV  


4

2
2
88
2
>
&$
r   z/gov/motie/heads_test/debugd   i  )r    geler   
str | Nonerf   c           
        s   zt ddd jpg }W n ty   g }Y nw g }|D ]H}|dp+d}|dp2d}t|}t	|}	| rF| |vrF| |vrFq#|rQ||vrQ||	vrQq#|
|d||||	|dd	 t||krk nq#t||d
S )u   정규화 결과를 JSON으로 확인하는 디버그 엔드포인트.
    dep/pos 필터를 주면 해당 문자열이 포함된 원본/정규화 값을 함께 반환한다.
    r8   r9   r:   r?   r   r-   r,   r.   )r,   r~   rZ   r   r[   r.   )countr{   )r   rc   rd   rf   rg   rh   ri   rU   r   r   r<   rK   )
r   r   rf   r{   outrY   r~   r   rZ   r[   r   r   r   heads_test_debug   sF   	r   r*   c                 C  s   t | }|dv r
dS |dv rdS |drd|vrdS dS |d	r$d
S |dr+dS |dr2dS |dkr8dS |dsB|drDdS |drKdS |drRdS |drYdS |dr`dS |drgdS |drndS dS )N)rO   u   1차관)rP   u   2차관u   본부장실u   통상u	   본부장u   통상교섭본부장	   위원회u	   위원장	   사무국u   사무국장u	   관리원u   원장rH   	   정책관	   기획관u   국장u	   관리관   실u   실장   국u   관   과u   과장   팀u   팀장r/   r   rI   r*   ur   r   r   _guess_expected_pos-  s<   









r   c                 C  sJ   t | }|dv r
dS |ds|dv rdS |drdS |dr#d	S dS )
N)u	   장관실rO   rP   u   통상교섭본부장실r   )r   )rH   r   )r   r   r   r   rB   )r   r   r   rC   r   r   r   r   r   _guess_indentO  s   

r   z!/gov/motie/heads_test/target_syncr)   applyupdate_existingc              
     s  zt ddd jpg }W n ty   g }Y nw tdd |D }zt ddjdd	d
d jp=g }W n tyJ   g }Y nw dd |D }t	dd |D dg }g }g }	|D ]B}
|
|vr}|d7 }|
||
t|
t|
d qd|r||
 }t|
}t|
}|d|ks|d|kr|	
|d|
||d qdt|t|t||rt|	nd|dd |	dd d}| s|S zXtdt|dD ]}|||d  }|rt d|  q|r|	r|	D ]}t d|d |d |d dd|d   qt||d< |rt|	nd|d< |W S  ty@ } ztd	t|d|ddW  Y d}~S d}~ww )u   motie_org_cur의 부서 목록을 기준으로 motie_heads_target을 자동 보강.
    - apply=0: 미리보기만(JSON)
    - apply=1: 누락 unit만 삽입(ord는 max+1부터), update_existing=1이면 기대직위/indent 업데이트
    r8   r?   r:   c                 S  s0   h | ]}| d p
d r| d pd qS )r?   r   rU   r   r1   rY   r   r   r   r_   p  s   0 z)heads_test_target_sync.<locals>.<setcomp>motie_heads_targetzord,unit,expected_pos,indentr&   Fr'   r)   c                 S  s    i | ]}| d p
d |qS )r*   r   r   r   r   r   r   
<dictcomp>~  s     z*heads_test_target_sync.<locals>.<dictcomp>c                 S  s   g | ]	}| d p
dqS )r&   r   rT   r   r   r   r   r3     s    z*heads_test_target_sync.<locals>.<listcomp>r   r   )r&   r*   r   r+   r   r+   N   )
total_depsexisting_targetsmissing_unitswill_updatesample_insertssample_updatesi  r*   )r*   r   r+   applied_insertsapplied_updates)okerror)status_code)r   rc   rd   rf   rg   rh   ri   sortedre   maxr<   r   r   rU   rK   rangeupsertupdateeqr
   r   )r   r   rf   deps	dep_namestgtby_unitmax_ordinsertsupdatesrW   curnew_epnew_indpreviewr}   partr   rL   r   r   r   heads_test_target_sync[  s   


	
&r   )r   r   r   r   )r!   r   r"   r   r#   r$   )r   r   r   r   rf   r$   )r*   r   r   r   )r*   r   r   r$   )r   r$   r   r$   rf   r$   )%
__future__r   typingr   r   r   r   ru   loggingfastapir   r   r   fastapi.responsesr	   r
   app.web.depsr   r   headsr   rq   r   r   _normalize_position_baser   r   r   router	getLoggerr=   rU   r   r   r   r   r   r   r   r   r   <module>   s<     	

 X
,
"