Ë
    ûªïi  ã                  óÊ   — d Z ddl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  ee«      Zd	Zd
ZdZdZdZdZdZdZddd„Zdd„Zdd„Zdd„Zdd„Zdd„Zd d„Z y)!u¢  
services/participant_repo.py
============================
Data-access layer for the `participant` table in the e-Recruit Postgres DB.

Responsibilities:
  â€¢ Look up a participant by `access_key` (case-insensitive).
  â€¢ Log the full DB row during initial bring-up (LOG_DB_PAYLOAD env flag).
  â€¢ Map raw DB columns to a canonical, route-friendly dict.
  â€¢ Be tolerant of column-name variations (e.g., participant_id vs id,
    candidate_name vs name, stage vs current_stage).
  â€¢ Optionally update last-login timestamp without breaking if the column
    doesn't exist in the target schema.

Nothing else in the codebase should query the participant table directly.
é    )Úannotations)ÚdatetimeÚtimezone)ÚAny)Úsql)Úsettings)Údatabase)Ú
get_logger)ÚidÚparticipant_idÚcandidate_idÚuidÚuuid)ÚnameÚcandidate_nameÚparticipant_nameÚ	full_nameÚdisplay_name)ÚemailÚemail_idÚemail_address)ÚphoneÚmobileÚ	mobile_noÚ
contact_no)Úcurrent_stageÚstageÚstage_noÚinterview_stage)Ú
access_keyÚ	accesskeyÚaccess_codeÚ	login_key)Úposition_appliedÚpositionÚrole_appliedÚjob_roleÚdesignation)Ú	skill_setÚskillsÚskillNc                ó6   — |D ]  }|| v sŒ| |   €Œ| |   c S  |S )zCReturn the value from the first key present in `row`, else default.© )ÚrowÚ
candidatesÚdefaultÚcs       út/Users/priyanka/Documents/AI_Agent_Assessment/pepole_hub_candidate/people_hub_candidate/services/participant_repo.pyÚ_first_presentr3   -   s,   € ãˆØ�Š8˜˜A™Ñ*Ø�q‘6ŠMð ð €Nó    c                ót  — | €g S t        | t        «      rA| D �cg c]5  }t        |«      j                  «       sŒt        |«      j                  «       ‘Œ7 c}S t        | t        «      r>| j	                  d«      D �cg c]#  }|j                  «       sŒ|j                  «       ‘Œ% c}S t        | «      gS c c}w c c}w )zKSkills column might be text[] or comma-separated string. Normalize to list.Ú,)Ú
isinstanceÚlistÚstrÚstripÚsplit)ÚvalueÚvÚss      r2   Ú_coerce_skillsr?   5   sŽ   € à€}Øˆ	Ü�%œÔÙ(-Ó@© 1´°Q³·±µ”�A“—‘•¨Ñ@Ð@Ü�%œÔØ#(§;¡;¨sÔ#3ÓAÑ#3˜a°q·w±wµy�—‘•	Ð#3ÑAÐAÜ�‹Jˆ<Ðùò AùâAs   ™B0¸B0Á9B5ÂB5c                óv   — | €y	 t        | «      S # t        t        f$ r t        j	                  d| «       Y yw xY w)zBStage column might be int, str or NULL. Default to 1 (Assessment).é   u4   Could not parse current_stage=%r â€” defaulting to 1)ÚintÚ	TypeErrorÚ
ValueErrorÚlogÚwarning)r<   s    r2   Ú_coerce_stagerG   @   s?   € à€}ØðÜ�5‹zÐøÜ”zÐ"ò Ü�‰ÐJÈEÔRÙðús   …
 �%8·8c                óÖ  — t        | t        d«      }t        | t        d«      }t        | t        d«      }t        | t        d«      }t        t        | t        d«      «      }t        | t        d«      }t        | t        d«      }t        t        | t        d«      «      }|�t        |«      ndt        |xs d«      t        |xs d«      t        |xs d«      |t        |xs d«      j                  «       t        |xs d«      || j                  d«      | j                  d«      | j                  «       D �	�
ci c](  \  }	}
|	t        |
t         «      s|
n|
j#                  «       “Œ* c}
}	dœS c c}
}	w )u‘   
    Map a raw participant row â†’ canonical dict used by the rest of the app.
    Original raw row is preserved under `_raw` for debugging.
    Ú Ú	CandidaterA   NÚ
last_loginÚlast_question_attempt)r   r   r   r   r   r    r$   r)   rK   rL   Ú_raw)r3   Ú_ID_COLSÚ
_NAME_COLSÚ_EMAIL_COLSÚ_PHONE_COLSrG   Ú_STAGE_COLSÚ	_KEY_COLSÚ_POSITION_COLSr?   Ú_SKILLS_COLSr9   ÚupperÚgetÚitemsr7   r   Ú	isoformat)r.   Úpidr   r   r   r   Úkeyr%   r*   Úkr=   s              r2   Ú
_normalizer]   K   s;  € ô
 ˜s¤H¨bÓ1€CÜ˜s¤J°Ó<€DÜ˜s¤K°Ó4€EÜ˜s¤K°Ó4€EÜœn¨S´+¸qÓAÓB€EÜ˜s¤I¨rÓ2€CÜ˜s¤N°BÓ7€HÜœ~¨c´<ÀÓFÓG€Fð ),¨œC œH¸RÜ Ò 3¨Ó4Ü ¢¨Ó,Ü ¢¨Ó,Ø!Ü ¢	 r›N×0Ñ0Ó2Ü ¢¨BÓ/Ø"ØŸG™G LÓ1Ø!$§¡Ð)@Ó!Aà*-¯)©)¬+ô7Ù*5¡$ ! Qð ¬*°Q¼Ô*A¡ÀqÇ{Á{Ã}ÑTØ*5ò7ñð ùó7s   Ä2-E%c                ó<  — | sy| j                  «       j                  «       }t        j                  t        j
                  «      }t        j                  d«      j                  |¬«      }t        j                  d|«       	 t        j                  «       5 }|j                  ||f«       |j                  «       }ddd«       st        j!                  d|«       yt#        |«      }t        j$                  rCt        j                  d|«       t        j                  dt'        |j)                  «       «      «       t+        |«      }t        j                  d	|d
   |d   |d   |d   «       |S # 1 sw Y   Œ²xY w# t        $ r}t        j                  d|«       ‚ d}~ww xY w)z
    SELECT * FROM <participant> WHERE UPPER(access_key) = UPPER(%s)
    Returns the normalized participant dict, or None.
    Nz:SELECT * FROM {table} WHERE UPPER(access_key) = %s LIMIT 1)Útableu,   [participant] login lookup â†’ access_key=%sz![participant] DB query failed: %sz4[participant] no participant found for access_key=%su   [participant] raw DB row â†’ %su&   [participant] columns available â†’ %su@   [participant] login resolved â†’ id=%s name=%s stage=%d email=%sr   r   r   r   )r:   rV   r   Ú
Identifierr   ÚDB_TABLE_PARTICIPANTÚSQLÚformatrE   ÚinfoÚdbÚ
get_cursorÚexecuteÚfetchoneÚ	ExceptionÚ	exceptionrF   ÚdictÚLOG_DB_PAYLOADÚsortedÚkeysr]   )Úraw_keyr[   r_   ÚqueryÚcurr.   ÚexcÚ
normalizeds           r2   Úfind_by_access_keyrt   k   sP  € ñ
 Øà
�-‰-‹/×
Ñ
Ó
!€CÜ�N‰Nœ8×8Ñ8Ó9€Eô �G‰GØDóç�f�5€fÓð 
ô ‡H�HÐ;¸SÔAðÜ�]‰]Œ_ Ø�K‰K˜ ˜vÔ&Ø—,‘,“.ˆC÷ ñ Ü�‰ÐJÈCÔPØä
ˆs‹)€Cä×Òä�‰Ð2°CÔ8Ü�‰Ð9¼6À#Ç(Á(Ã*Ó;MÔNä˜C“€JÜ‡H�HØJØ�4Ñ˜* VÑ,Ø�?Ñ# Z°Ñ%8ôð
 Ð÷1 ˆ_ûô ò Ü�‰Ð9¸3Ô?Øûðús0   ÂE6 Â$E*Â9E6 Å*E3Å/E6 Å6	FÅ?FÆFc                óF  — | syt        j                  t        j                  «      }d}t        D ]�  }t        j
                  d«      j                  |t        j                  |«      ¬«      }	 t        j                  «       5 }|j                  |t        | «      f«       |j                  «       }ddd«       rt        t        |«      «      c S ŒŸ |rt        j#                  d|«       y# 1 sw Y   Œ<xY w# t        $ r#}|}t        j!                  d||«       Y d}~Œìd}~ww xY w)zDLook up a participant row by primary id. Tries each known id column.Nz4SELECT * FROM {table} WHERE {col}::text = %s LIMIT 1©r_   Úcolz)[participant] id lookup via %s failed: %sz4[participant] id lookup exhausted all candidates: %s)r   r`   r   ra   rN   rb   rc   re   rf   rg   r9   rh   r]   rk   ri   rE   ÚdebugrF   )r   r_   Úlast_errÚid_colrp   rq   r.   rr   s           r2   Ú
find_by_idr{   š   sî   € áØä�N‰Nœ8×8Ñ8Ó9€EØ!%€HçˆÜ—‘ØBó
ç
‰&�u¤#§.¡.°Ó"8ˆ&Ó
9ð 	ð		Ü—‘” CØ—‘˜E¤C¨Ó$7Ð#9Ô:Ø—l‘l“n�÷ !ñ Ü!¤$ s£)Ó,Ò,ð ð ñ Ü�‰ÐJÈHÔUØ÷ !�ûô
 ò 	ØˆHÜ�I‰IÐAÀ6È3ÔOÜûð	ús0   Á,C4Â -C(Â-C4Ã(C1	Ã-C4Ã4	D Ã=DÄD c           	     ó–  — | syt        j                  t        j                  «      }t	        j
                  t        j                  «      }t        D ]©  }t	        j                  d«      j                  |t	        j
                  |«      ¬«      }	 t        j                  d¬«      5 }|j                  ||t        | «      f«       |j                  dkD  r!t         j#                  d| «       	 ddd«        y	 ddd«       Œ« t         j#                  d	«       y# 1 sw Y   Œ!xY w# t$        $ r!}t         j#                  d||«       Y d}~Œód}~ww xY w)
z˜
    Best-effort: update last_login = now(). If the column doesn't exist
    in the target schema, swallow the error rather than failing the login.
    Nz9UPDATE {table} SET last_login = %s WHERE {col}::text = %srv   F)Ú	dict_rowsr   z'[participant] last_login updated for %sz1[participant] last_login update via %s failed: %szA[participant] last_login not updated (no compatible column / row))r   Únowr   Úutcr   r`   r   ra   rN   rb   rc   re   rf   rg   r9   ÚrowcountrE   rx   ri   )r   r~   r_   rz   rp   rq   rr   s          r2   Útouch_last_loginr�   ¶   sý   € ñ
 Øä
�,‰,”x—|‘|Ó
$€CÜ�N‰Nœ8×8Ñ8Ó9€EçˆÜ—‘ØGó
ç
‰&�u¤#§.¡.°Ó"8ˆ&Ó
9ð 	ð		Ü—‘¨Õ/°3Ø—‘˜E C¬¨^Ó)<Ð#=Ô>Ø—<‘< !Ò#Ü—I‘IÐGÈÔXØ÷	 0Ñ/à#÷ 0øð ô ‡I�IÐQÕR÷ 0Ð/ûô
 ò 	ä�I‰IÐIÈ6ÐSVÔWÜûð	ús7   ÂDÂ#ADÃ'DÃ2DÄD	ÄDÄ	EÄ'EÅE)N)r.   rk   r/   ztuple[str, ...]r0   r   Úreturnr   )r<   r   r‚   z	list[str])r<   r   r‚   rB   )r.   rk   r‚   rk   )ro   r9   r‚   údict | None)r   r9   r‚   rƒ   )r   r9   r‚   ÚNone)!Ú__doc__Ú
__future__r   r   r   Útypingr   Úpsycopg2r   Úconfigr   Úutilsr	   re   Úutils.loggerr
   Ú__name__rE   rN   rO   rP   rQ   rR   rS   rT   rU   r3   r?   rG   r]   rt   r{   r�   r-   r4   r2   Ú<module>r�      s|   ðñõ  #ç 'Ý å å Ý  Ý #á�Ó€ð F€ØY€
Ø4€Ø<€ØG€ØE€	Ø\€Ø/€ôóóóó@,ó^ô8Sr4   