U
    i`                  
   @   s>  d dl mZmZm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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Zd d
lZe Ze d e d e d dZ!dZ"e de!  e dej#$e!  e dej#%e!  z<e&e!dddZ'e(e'Z)W 5 Q R X e de*e) d W n6 e+k
rv Z, ze de,  g Z)W 5 d
Z,[,X Y nX e de"  e dej#$e"  e dej#%e"  di iZ-ej#$e"rܐzhe d e&e"ddd:Z'e'. Z/e de*e/ d e de/d
d  d  W 5 Q R X e d! e&e"dddZ'e(e'Z-W 5 Q R X e d" e d# e d$e0e-  e d%e1e-2   de-kr(e-d Z3e d&e0e3  e d'e*e3  e d( e4e32 d)d* d+D ]LZ5e3e5 6d,d-Z7e3e5 6d.g Z8e d/e5 d0e0e5j9 d1e7 d2e8  qne d3 W n ej:k
r Z, z2e d4e,  e d5e,j; d6e,j<  di iZ-W 5 d
Z,[,X Y nT e+k
r Z, z4e d7e,  d d
l=Z=e d8e=>   di iZ-W 5 d
Z,[,X Y nX ne d9 e d: di iZ-e d e d; e d< G d=d> d>eZ?G d?d@ d@eZ@dAdB ZAdCdD ZBdEdF ZCi ZDzNe1eEedGg ZFeGeFD ]0\ZHZIeJdHdI eK D d
ZLeLeIdJeDeH< qbW n2 e+k
r Z, ze dKe,  W 5 d
Z,[,X Y nX e dLeD eMe
eeM dMdNdOZNeMeeM dPdQdRZOeeM dSdTdUZPdVdW ZQeRdXeefe@e
dYdZd[ZSd
S )\    )	APIRouterHTTPExceptionDepends)	BaseModel)ListOptional)Session)select   )	odd_classifierodd_label_encoder	odd_namesnature_classifiernature_label_encodernature_namescible_classifierindicateur_classifierhierarchy_data)get_db)Activity	DirectionMinistryNzQ
================================================================================u9   🔍 DÉBOGAGE DÉTAILLÉ DU CHARGEMENT DES FICHIERS JSONzP================================================================================z7/var/www/html/mes-ia-odd/models/cibles_indicateurs.jsonz9/var/www/html/mes-ia-odd/models/ministry_odd_mapping.jsonu   
Vérification de: z   Existe? z   Chemin absolu: rzutf-8)encodingu    Chargé avec succès: u    élémentsz	 Erreur: u   
 Vérification de: mappingsz Lecture du fichier...z   Taille du fichier: u    caractèresu      Premiers 200 caractères:
   ...z
   Parsing JSON...u      JSON parsé avec succès!z
   Structure du JSON:z     Type: u        Clés principales: z      Type de 'mappings': u         Nombre de ministères: u%   
   Toutes les clés dans 'mappings':c                 C   s   t | S Nintx r"   @/var/www/html/mes-ia-odd/micro-service/app/routers/activities.py<lambda>D       r$   keyministry_nameN/Aodd_idsu         • Clé: '	' (type:    ) → u    → ODDs: u6         ⚠️Clé 'mappings' non trouvée dans le JSON!z   Erreur de parsing JSON: z      Position: ligne z
, colonne z   Erreur inattendue:       Traceback:
u      Fichier non trouvé!u2      Essayez de créer le fichier à cet emplacementu   CHARGEMENT TERMINÉzQ================================================================================
c                   @   s   e Zd ZU eed< eed< dS )ActivityItemnameidN)__name__
__module____qualname__str__annotations__r   r"   r"   r"   r#   r.   ^   s   
r.   c                   @   s   e Zd ZU ee ed< dS )ActivitiesRequest
activitiesN)r1   r2   r3   r   r.   r5   r"   r"   r"   r#   r6   b   s   
r6   c                 C   s*   | sdS | d }t |tr&|r&|d S |S )u9   Retourne le premier dict d'une liste ou liste imbriquée.Nr   )
isinstancelist)Zpredsfirstr"   r"   r#   get_first_predictionf   s    r;   c                 C   sH   dd l }t| |jrt| S t| |jr0t| S t| |jrDt| S | S )Nr   )Znumpyr8   integerr   ZfloatingfloatZbool_bool)objnpr"   r"   r#   	to_nativeo   s    rA   c                 C   s<   ddddddddddd	dd
}dd	d}| | |S )NP      )ZsensitivityZappreciation_id<      (   r
         )rH   r
   rE   rC   g      4@get)	nature_idmappingZdefault_valuesr"   r"   r#   get_dynamic_valuesy   s    
rM   classes_c                 c   s"   | ]\}}|t krt|V  qd S r   )
label_namer   .0kvr"   r"   r#   	<genexpr>   s      rT   r0   r/   z2Erreur lors de la construction du nature_mapping: u,   Mapping du modèle Nature → IDs métiers :)activity_iddbreturnc              
   C   s6  t d|  d t dd  zddlm} t d|  d |t|tjtj	tj
| k }|s~t d	 W d
S t d|jd
d  d t d t d|j
  t dt|j   d
}d|jkr|jd }t d|  z,t|dd
}t d|  |d
kr|}W n2 tk
rL } zt d|  W 5 d
}~X Y nX z<t|dr|jr|jj
}t d|  |d
kr|}W n2 tk
r } zt d|  W 5 d
}~X Y nX |st d W d
S t d| d |t	tj
|k }|st d W d
S t d|jd
d  d t d t d|j
  t dt|j   d
}	d|jkr|jd }	t d|	  z,t|dd
}
t d |
  |	d
kr|
}	W n2 tk
r } zt d|  W 5 d
}~X Y nX z<t|d!r|jr|jj
}t d"|  |	d
kr|}	W n2 tk
rP } zt d|  W 5 d
}~X Y nX |	sft d# W d
S |t	tj
|	k }|rt d$|j  nt d%|	 d& t d'|	 d(t|	j d t dd  |	W S  tk
r0 } z:dd
l}t d) t d*|  t d+|   W Y d
S d
}~X Y nX d
S ),uo   
    Récupère l'ID du ministère à partir de l'ID de l'activité.
    VERSION AVEC DÉBOGAGE DÉTAILLÉ
    u5   
   DÉBOGAGE get_ministry_from_activity(activity_id=)      ──────────────────────────────────────────────────────────────────────r   )
joinedloadu     Recherche de l'activité ID=r   u!      Activité non trouvée en baseNu      Activité trouvée: 2   u      Attributs de l'activité:u         • activity.id: u$         • activity.__dict__.keys(): direction_idu0         • Méthode 1 (__dict__): direction_id = u/         • Méthode 2 (getattr): direction_id = u         • Méthode 2 échec: 	directionu0         • Méthode 3 (relation): direction_id = u         • Méthode 3 échec: u)      Impossible de récupérer direction_idz!
   Recherche de la direction ID=u      Direction non trouvéeu      Direction trouvée: z   Attributs de la direction:u         • direction.id: u%         • direction.__dict__.keys(): ministry_idu/         • Méthode 1 (__dict__): ministry_id = u.         • Méthode 2 (getattr): ministry_id = ministryu/         • Méthode 3 (relation): ministry_id = u,      ❌ Impossible de récupérer ministry_idu      Ministère trouvé: u      Ministère ID=u    existe mais pas récupéréu#   
   RÉSULTAT FINAL: ministry_id = z (type: z   ERREUR EXCEPTION:z      Message: r-   )printsqlalchemy.ormr\   queryr   optionsr_   r   ra   filterr0   r:   r/   r9   __dict__keysgetattr	Exceptionhasattrr   typer1   	traceback
format_exc)rV   rW   r\   activityr^   Zdirection_id_attreZdirection_id_relr_   r`   Zministry_id_attrZministry_id_relra   rm   r"   r"   r#   get_ministry_from_activity   s    



 
 

 
 rq   )r`   rX   c           
         sB  t d  d t dd  t d t d   t dt j  t dt   t }t d	 t d
| d t dt|j  t dt|  t dt|  t d t dtt  t dtt   t	di }t dt|  t dt|  |r8t d t
t| dd dD ]P\}}|| 	dd}t d|d dd| dt|j dt| d| 
 q8t d  t d!| d t d"||k  t d#|| k  t d$ | D ]Z}||k}| rt  rt|t|knd%}t d&| d'| d(| d)|  qnt d* ||kr|| d+ }|| 	dd,}t d- t d.|  t d/|  t dd  |S t d0| d t d1 t d2 |r fd3d4| D }	|	rt d5|	  t |kr"t d6 t d7 nt d8 t d9t  t dd  ttdd:S d;S )<ux   
    Retourne la liste des IDs des ODDs autorisés pour un ministère donné.
    VERSION AVEC DÉBOGAGE DÉTAILLÉ
    u8   
   DÉBOGAGE get_allowed_odds_for_ministry(ministry_id=rY   rZ   r[   z    Analyse de ministry_id:u         • Valeur: u         • Type: u         • repr(): u   
   Clé de recherche:u         • ministry_key: ''u         • Longueur: u   
   État du mapping:u(         • Type de ministry_odd_mapping: u)         • Clés de ministry_odd_mapping: r   u         • Type de mappings: u+         • Nombre d'entrées dans mappings: u/   
   TOUTES les clés disponibles dans mappings:c                 S   s   |   rt| S dS )Ni  )isdigitr   r    r"   r"   r#   r$   '  r%   z/get_allowed_odds_for_ministry.<locals>.<lambda>r&   r(   r)   z      rH   Z2du	   . Clé: 'r+   z, repr: r,   z
   Test de correspondance:u!         • Recherche de la clé: 'u$         • ministry_key in mappings: u+         • ministry_key in mappings.keys(): u-   
   🧪 Comparaison exacte avec chaque clé:Fu         • 'z' == 'z': z | int comparison: z(    Le dictionnaire 'mappings' est vide!r*   ZInconnuu   
   MAPPING TROUVÉ!u         • Ministère: u         • ODDs autorisés: u&   
   MAPPING NON TROUVÉ pour la clé 'u9         • Utilisation de tous les ODDs (1-17) par défautz
   SUGGESTIONS:c                    s(   g | ] }t  |ks |t  kr|qS r"   r4   )rQ   rR   r`   r"   r#   
<listcomp>I  s       z1get_allowed_odds_for_ministry.<locals>.<listcomp>u&         • Clés similaires trouvées: u@         • ATTENTION: La clé existe mais la comparaison échoue!u9         • Vérifiez les espaces ou caractères invisiblesu1         • Le fichier JSON est vide ou mal chargéu         • Vérifiez le chemin:    N)rb   rl   r1   reprr4   lenministry_odd_mappingr9   rh   rJ   	enumeratesortedrs   r   ministry_odd_map_pathrange)
r`   Zministry_keyr   idxr'   r(   is_equalZis_equal_intZallowed_oddsZclose_matchesr"   ru   r#   get_allowed_odds_for_ministry  sn     :,&

r   )allowed_odd_idsc                 C   s  | sg S t | d tr| d n| }g }|D ]N}|dd}t |tr^|dr^t|ddnt|}||kr*|| q*|jdd dd	 t	d
t
| dt
| d |dd D ]^}|dd}t |tr|drt|ddnt|}|dd}t	d| d|d q|S )u   
    Filtre les prédictions du modèle ODD pour ne garder que celles
    qui correspondent aux ODDs autorisés pour le ministère.
    r   labelLABEL_0LABEL_ c                 S   s   |  ddS )Nscorer   rI   r    r"   r"   r#   r$   k  r%   z(filter_odd_predictions.<locals>.<lambda>T)r'   reverseu      Prédictions filtrées: /u    ODDs conservésNrE   r   z      - ODD z: score=.4f)r8   r9   rJ   r4   
startswithr   replaceappendsortrb   ry   )Zpredictionsr   Z
preds_listfilteredpredr   odd_idr   r"   r"   r#   filter_odd_predictionsY  s"    ,,r   c                    sB  z:t | tr0|  dr0t| ddd }nt| }W n tk
rP   Y dS X d zttdrrt	|gd  W n tk
r   d Y nX  dkrz,t
tdd}|dk	rt||kr||  W n tk
r   d Y nX  rt fd	d
t D d}|dk	r|| fS t|}|r8||d|dfS |d fS )zg
    label: 'LABEL_0' ou '0' ou 0
    retourne: (model_idx, metier_id_or_None, class_name_or_None)
    r   _rH   )NNNNinverse_transformr   rN   c                 3   s"   | ]\}}| krt |V  qd S r   r   rP   
class_namer"   r#   rT     s      z,map_model_label_to_nature.<locals>.<genexpr>r0   r/   )r8   r4   upperr   r   splitrj   rk   r   r   ri   ry   nextr   itemsnature_mappingrJ   )r   	model_idxZclasses_attrZ	metier_idinfor"   r   r#   map_model_label_to_naturew  s6    





r   z/analyse-activities)requestrW   c           )   
      sL  zt dd  t dt| j d t d  g }t| jD ]l\}}|j}|j}t dd  t d|d  dt| j  t d	|  t d
| d t d  t d t||}|d krt d ttdd}nt	|}t d t
|}	t d|	r
t|	d nd d t|	|}
|
s0t d q@|
d }t d|  |dd}t|trz|drzt|ddnt|ttd }|dd}t d d| d|d t d t|}t|}|sttd d! t D d"}tt|d#}n|dd}t|\}}|d k	r:|}}nrtfd$d!t D d }|rl|}}n,ttd%d! t D d"}tt|d#}n,ttd&d! t D d"}tt|d#}t d' fd(d)tD }d }|rt|}t|}d  |r||dd*}z4t|tr:|dr:t|ddnt| W n   |d d+  Y nX t fd,d!|D |d }n|d }t d- d }d.}|rHd/|krH|d/ rH|d/ }t|}t|} | rH| dd*}!z4t|!tr|!drt|!ddnt|!}"W n   d}"Y nX |"t| }"||" }#|#d0}|#d1d.}||||d2||d2|rl|d+ nd |r||d3 nd4d2||d2d5}$||$ t d6|d  d7 q@t dd  t d8t| d9 t d  d:|i}%|%W S  tk
rF }& z>dd l}'d;t|& d<|'  }(t d=|(  t d>|(d?W 5 d }&~&X Y nX d S )@N
z<============================================================u   DÉBUT DE L'ANALYSE - u    activité(s) à traiterz(========================================u    ACTIVITÉ #rH   r   z   ID: z	   Nom: 'rr   u(   
 ÉTAPE 0: Récupération du ministèreuN      Impossible de déterminer le ministère - Tous les ODDs seront considérésrw   u5   
 ÉTAPE 1: Prédiction ODD (filtrée par ministère)u      Prédictions brutes ODD: r   u    prédictionsuF       Aucune prédiction ODD valide après filtrage - Activité ignoréeu'      Meilleure prédiction ODD filtrée: r   r   r   r   zODD r   u      ODD sélectionné: ID=z, Nom='z	', Score=r   u   
 ÉTAPE 2: Prédiction Naturec                 s   s   | ]\}}|d kr|V  qdS SoutienNr"   rP   r"   r"   r#   rT     s      z%analyse_activities.<locals>.<genexpr>4r   c                 3   s"   | ]\}}| krt |V  qd S r   r   rP   )mapped_namer"   r#   rT     s      c                 s   s   | ]\}}|d kr|V  qdS r   r"   rP   r"   r"   r#   rT     s      c                 s   s   | ]\}}|d kr|V  qdS r   r"   rP   r"   r"   r#   rT     s      u+   
 ÉTAPE 3: Recherche des cibles pour l'ODDc                    s$   g | ]}t |d  t  kr|qS )Zodd_codert   rQ   c)r   r"   r#   rv     s      z&analyse_activities.<locals>.<listcomp>0cible_idc                 3   s   | ]}|d   kr|V  qdS )r   Nr"   r   )r   r"   r#   rT     s      u&   
 ÉTAPE 4: Sélection de l'indicateurzAucun indicateur disponibleZindicateursr0   r/   rU   cibleZInconnue)ro   rV   r`   ZoddZnaturer   Z
indicateuru   
 Activité #u    traitée avec succès!z FIN DE L'ANALYSE - u    résultat(s) généré(s)resultszErreur analyse : z
Traceback: z
 ERREUR GLOBALE: i  )status_codedetail)!rb   ry   r7   r{   r/   r0   rq   r9   r~   r   r   r   rJ   r8   r4   r   r   r   r   r   r;   r   r   r   r   cibles_datar   r   r   rj   rm   rn   r   ))r   rW   r   iZactivity_itemZact_namerV   r`   r   Zodd_predictionsZfiltered_odd_predictionsZodd_predZ	odd_labelZodd_nameZ	odd_scoreZnature_predictionsZnature_predrK   Znature_name_strZnature_labelr   Z	mapped_idZapprox_matchZpossible_ciblesZcible_matchZcible_predictionsZ
cible_predZcible_labelZindicateur_idZindicateur_nameZindicateurs_disponiblesZindicateur_predictionsZindicateur_predZ	ind_labelZind_idZselected_indicateurZresult_itemZfinal_responserp   rm   Zerror_detailsr"   )r   r   r   r#   analyse_activities  s    


"
0
44

$


r   )Tfastapir   r   r   pydanticr   typingr   r   rc   r   
sqlalchemyr	   Z	ml_modelsr   r   r   r   r   r   r   r   r   databaser   modelsr   r   r   jsonosrouterrb   	json_pathr}   pathexistsabspathopenfloadr   ry   rj   rp   rz   readZfile_contentrl   r9   rh   r   r|   r'   rJ   r(   r*   r1   JSONDecodeErrorlinenocolnorm   rn   r.   r6   r;   rA   rM   r   ri   classesr{   r   rO   r   r   matchr   rq   r   r   r   postr   r"   r"   r"   r#   <module>   s   ,"
,	
 
vS(