
    (OjW                    *   S r SSKJr  SSKrSSKJrJr  SSKJr  SSK	J
r
JrJrJr  SSKrSSKJr  SSKJr  SS	KJrJr  \R.                  S
-  r\R.                  S-  r\R.                  S-  r\R.                  S-  r\ " S S5      5       r " S S5      rg)a  
import_utils.py

Utility module for importing and validating
LeafDoctor AI datasets.

Responsibilities
----------------
1. Read CSV files
2. Clean data
3. Validate data
4. Import into PostgreSQL
5. Generate crop-label mapping
6. Generate import report

Author: LeafDoctor AI
    )annotationsN)	dataclassfield)Path)DictListOptionalSet)Session)settings)ProtectionLabelTreatmentMappingzcrop_protection_labels.csvz&normalized_class_treatment_mapping.csvzcrop_label_mapping.jsonzimport_report.jsonc                      \ rS rSr% SrS\S'   SrS\S'   SrS\S'   SrS\S'   Sr	S\S'   Sr
S\S	'   SrS\S
'   SrS\S'   SrS\S'   \" \S9rS\S'   \" \S9rS\S'   S rSrg)ImportReport=   r   intmaster_labelstreatment_recordsimported_labelsimported_treatmentsduplicate_labelsduplicate_class_idsorphan_class_idslabel_mismatchesskipped_rows)default_factoryz
List[dict]warningsz	List[str]errorsc                    U R                   U R                  U R                  U R                  U R                  U R
                  U R                  U R                  U R                  U R                  U R                  S.$ )Nr   r   r   r   r   r   r   r   r   r   r   r    selfs    ,/var/www/html/leaf-doctor-v1/import_utils.pyto_dictImportReport.to_dictV   sm     "//!%!7!7#33#'#;#; $ 5 5#'#;#; $ 5 5 $ 5 5 --kk
 	
     N)__name__
__module____qualname____firstlineno__r   __annotations__r   r   r   r   r   r   r   r   r   listr   r   r$   __static_attributes__r'   r&   r#   r   r   =   s     M3sOS  c  ccL# 6Hj6d3FI3
r&   r   c                      \ rS rSrSS jrS r\S 5       r\S 5       rS r	S r
SS jrS	 rS
 rS rS rS rS rS rS rS rS rS rS rS rS rSrg)ImportUtilsl   c                f    Xl         [        5       U l        S U l        S U l        0 U l        0 U l        g N)dbr   report	labels_dftreatment_dfmaster_label_mapcrop_label_map)r"   r4   s     r#   __init__ImportUtils.__init__n   s/    "n15480235r&   c                   [         R                  5       (       d  [        [         5      e[        R                  5       (       d  [        [        5      e[        R
                  " [         5      U l        [        R
                  " [        5      U l        [        S5        [        U R                  R                  5        [        S5        [        U R                  R                  5        [        S5        [        U R                  R                  5       5        [        U R                  5      U R                  l        [        U R                  5      U R                  l        g )Nz
===== LABELS DTYPES =====z
===== TREATMENT DTYPES =====z
===== TREATMENT HEAD =====)
LABEL_FILEexistsFileNotFoundErrorTREATMENT_FILEpdread_csvr6   r7   printdtypesheadlenr5   r   r   r!   s    r#   load_csv_filesImportUtils.load_csv_files   s      ""#J//$$&&#N33Z0KK7+,dnn##$./d&&',-d$$&'$'$7!(+)
%r&   c                    [         R                  " U 5      (       a  g [        U 5      n U R                  5       n U S:X  a  g SR	                  U R                  5       5      n U $ )N  )rA   isnastrstripjoinsplitvalues    r#   clean_stringImportUtils.clean_string   sK     775>>E
B;'r&   c                r    [         R                  " U 5      (       a  g  [        U 5      $ ! [         a     g f = fr3   )rA   rL   r   	ExceptionrQ   s    r#   clean_integerImportUtils.clean_integer   s5     775>>	u: 		s   
) 
66c                0   U R                   R                   H8  nU R                   U   R                  U R                  5      U R                   U'   M:     U R                   S   R                  U R                  5      U R                   S'   U R
                  R                   H@  nUS:X  a  M  U R
                  U   R                  U R                  5      U R
                  U'   MB     U R
                  S   R                  U R                  5      U R
                  S'   g )NClass_ID)r6   columnsapplyrS   rW   r7   )r"   columns     r#   clean_dataframesImportUtils.clean_dataframes   s     nn,,F v&t(() NN6" - NN:&U4%%& 	z" ''//F# !!&)t(() f% 0 j)U4%%& 	*%r&   c                    U R                   R                  5         U R                  R                  5        H"  u  pUS   nUS   nUc  M  X@R                   U'   M$     g )NrZ   
Label_Name)r8   clearr6   iterrows)r"   _rowclass_idlabels        r#   build_master_lookupImportUtils.build_master_lookup   sW    ##%nn--/FA:H%E.3!!(+ 0r&   c                8    U R                   R                  U5      $ r3   )r8   get)r"   rf   s     r#   master_labelImportUtils.master_label   s    $$((22r&   c                n    [        5         [        S5        [        S5        [        S5        [        5         g )NF======================================================================zLeafDoctor AI Dataset ImportrC   r!   s    r#   print_headerImportUtils.print_header   s#    h,-hr&   c                n    [        5         [        S5        [        S5        [        S5        [        5         g )Nro   zDataset Loading Finishedrp   r!   s    r#   print_footerImportUtils.print_footer  s#    h()hr&   c                (   [        S5        U R                  U R                  S   R                  SS9   R                  S5      nUR                  (       df  US   R                  5       U R                  l        UR                  5        H0  u  p#U R                  R                  R                  SUS    35        M2     U R                  U R                  S   R                  SS9   R                  S5      nUR                  (       df  US   R                  5       U R                  l        UR                  5        H0  u  p#U R                  R                  R                  SUS    35        M2     U R                  U R                  S   R                  5          nUR                  (       dY  U R                  =R                  [        U5      -  sl        U R                  R                  R                  S[        U5       35        U R                  U R                  S   R                  5          nUR                  (       dZ  U R                  =R                  [        U5      -  sl        U R                  R                  R                  S	[        U5       35        g
g
)z 
Validate master label dataset.
zValidating master labels...rZ   F)keepzDuplicate Class_ID : ra   zDuplicate Label : zMissing Class_ID rows : zMissing Label rows : N)rC   r6   
duplicatedsort_valuesemptynuniquer5   r   rc   r   appendr   rL   r   rF   )r"   duplicate_idsrd   re   r   missing_idsmissing_labelss          r#   validate_master_labels"ImportUtils.validate_master_labels  s9   
 	+, NNz*5555A [$	 	 "" j)113 KK+ (002""))+C
O+<= 3 NN|,77U7C [&	 	  %% !.668 KK( +335""))(\):(;< 6 nnNN:&++-
   KK$$K(88$KK%%*3{+;*<= NN<(--/
 ##KK$$N(;;$KK%%'N(;'<=	 $r&   c                   [        S5        [        5       nU R                  R                  5        GH{  u  p#US   nUR	                  S5      nUcJ  U R
                  =R                  S-  sl        U R
                  R                  R                  SU S35        Mi  X@R                  ;  aC  UR                  U5        U R
                  R                  R                  [        U5      USS	.5        Uc2  U R
                  R                  R                  [        U5      US
S	.5        UR	                  S5      c2  U R
                  R                  R                  [        U5      USS	.5        UR	                  S5      b  GMI  U R
                  R                  R                  [        U5      USS	.5        GM~     [        U5      U R
                  l        g)z%
Validate treatment mapping dataset.
zValidating treatment mapping...rZ   CropN   zRow z: Missing Class_IDzOrphan Class_ID)re   rf   issuezMissing CropChemical & FormulationzMissing ChemicalSMS : Growth Stage 1zMissing SMS)rC   setr7   rc   rk   r5   r   r   r|   r8   addr   r   rF   r   )r"   
orphan_idsindexre   rf   crops         r#   validate_treatment_mapping&ImportUtils.validate_treatment_mappingo  s   
 	/0U
++446JE:H776?D((A-(""))5'!34 444x($$++"5z$,!2 |$$++"5z$,!/ ww/08$$++"5z$,!3 ww-.6$$++"5z$,!.e 7t (+:$r&   c                   [        S5        SnU R                  R                  5        H  u  p#US   nUc  M  X@R                  ;  a  M   U R                  U   nU R	                  UR                  S5      5      nUc  MT  XV:w  d  M[  US-  nU R                  R                  R                  [        U5      UUUS.5        M     XR                  l
        g)zA
Compare the label in treatment CSV
with the master label table.
zChecking label mapping...r   rZ   NMaster_Label_Namer   )re   rf   rl   	csv_label)rC   r7   rc   r8   rS   rk   r5   r   r|   r   r   )r"   
mismatchesr   re   rf   rl   r   s          r#   detect_mapping_mismatches%ImportUtils.detect_mapping_mismatches  s     	)*
++446JE:H44400:L))+,I  (a
$$++"5z$,(4%.	/ 7@ (2$r&   c                   U R                  5         U R                  5         U R                  5         [        5         [        S5        [        SU R                  R
                   35        [        SU R                  R                   35        [        SU R                  R                   35        [        SU R                  R                   35        [        SU R                  R                   35        [        5         g)z
Run every validation step.
zValidation CompleteDuplicate Labels      : Duplicate Class IDs   : Orphan Class IDs      : Label Mismatches      : Skipped Rows          : N)
r   r   r   rC   r5   r   r   r   r   r   r!   s    r#   validateImportUtils.validate  s    
 	##%'')&&(#$&{{++,.	

 	&{{../1	

 	&{{++,.	

 	&{{++,.	

 	&{{''(*	

 	r&   c                V   [        S5         U R                  R                  [        5      R	                  5         U R                  R                  [
        5      R	                  5         U R                  R                  5         g! [         a    U R                  R                  5         e f = f)zl
Clear master tables before importing.

Import is idempotent, so every execution starts
from a clean state.
zClearing existing data...N)	rC   r4   queryr   deleter   commitrV   rollbackr!   s    r#   clear_databaseImportUtils.clear_database  su     	)*	GGMM*+224GGMM/*113GGNN 	GG		s   A4B &B(c           	     v   [        S5        SnU R                  R                  5        HU  u  p#US   nUS   nUc  M  Uc  M  [        UUSUR	                  S5      SS9nU R
                  R                  U5        US-  nMW     U R
                  R                  5         XR                  l	        [        S	U S
35        g)z
Import master label table.
zImporting protection labels...r   rZ   ra   NPrimary_Category)rf   label_name_enlabel_name_bnprimary_category_enprimary_category_bnr   	Imported z labels.)
rC   r6   rc   r   rk   r4   r   flushr5   r   )r"   importedrd   re   rf   rg   objs          r#   import_protection_labels$ImportUtils.import_protection_labels2  s    
 	./nn--/FA:H%E}!!#"$'GG&% %)C  GGKKMHA 0D 	&.#	(8,-r&   c                   [        S5        SnSnU R                  R                  5        H  u  p4US   nUc  US-  nM  XPR                  ;  a  US-  nM*  [	        UUR                  S5      SUR                  S5      SUR                  S5      UR                  S	5      UR                  S
5      UR                  S5      SS9
nU R                  R                  U5        U R                  R                  5         US-  nM     [        [        W5      5        U R                  R                  5         XR                  l        U R                  =R                  U-  sl        [        SU S35        [        SU S35        g)z
Import treatment mapping.

IMPORTANT

We intentionally ignore Master_Label_Name
from the CSV because the master table
already contains the authoritative label.
zImporting treatment mapping...r   rZ   Nr   r   zType of Problemr   zChemical TypezRevised Dosagesr   )
rf   crop_encrop_bnproblem_type_enproblem_type_bnchemicalchemical_typedosagesms_ensms_bnr   z treatments.zSkipped z rows.)rC   r7   rc   r8   r   rk   r4   r   r   varsr5   r   r   )r"   r   skippedrd   re   rf   	treatments          r#   import_treatment_mapping$ImportUtils.import_treatment_mappingg  sd    	./''002FA:H14441(! #%! !%, "gg# ww% ww* = ID GGKK	" GGMMOMHo 3p 	d9o*2'  G+ 	(<01	()r&   c                   [        5         [        S5        [        S5        [        S5         U R                  5         U R                  5         U R                  5         U R                  R                  5         [        5         [        S5        g! [         aH  nU R                  R                  5         [        5         [        S5        [        [        U5      5      eSnAff = f)z)
Complete import inside one transaction.
z<============================================================zDatabase Import StartedzDatabase Import Completed.zDatabase Import FailedN)
rC   r   r   r   r4   r   rV   r   RuntimeErrorrM   )r"   exs     r#   import_databaseImportUtils.import_database  s    
 	h'(h	(!))+))+GGNNG./ 	(GGG*+s2w''	(s   AB 
CACCc                   [        S5        0 nU R                  R                  5        H  u  p#US   nX@R                  ;  a  M  U R	                  UR                  S5      5      nUc  M@  U R                  U   nXQ;  a  [        5       [        5       S.X'   X   S   R                  U5        X   S   R                  U5        M     0 n[        UR                  5       5       H$  u  pX[        US   5      [        US   5      S.Xu'   M&     [        [        SS	S
9 n	[        R                  " UU	SSS9  SSS5        [        S[         35        g! , (       d  f       N!= f)z~
Generate crop -> valid labels mapping.

Example

{
    "Rice": {
        "labels": [...],
        "class_ids": [...]
    }
}
z Generating crop-label mapping...rZ   r   N)labels	class_idsr   r   wutf-8encoding   Findentensure_asciizCrop mapping saved to )rC   r7   rc   r8   rS   rk   r   r   sorteditemsopenCROP_MAPPING_FILEjsondump)
r"   mappingrd   re   rf   r   rg   outputvaluesfps
             r#   generate_crop_label_mapping'ImportUtils.generate_crop_label_mapping  sW    	01''002FA:H444$$SWWV_5D|))(3E" "e!$!
 M(#''.M+&**84/ 32 "7==?3LD !!12#F;$78	FL 4 
 II"	
 	$ !#	

 
s   E
Ec                    [        [        SSS9 n[        R                  " U R                  R                  5       USSS9  S S S 5        [        S[         35        g ! , (       d  f       N!= f)Nr   r   r   r   Fr   zImport report saved to )r   IMPORT_REPORT_FILEr   r   r5   r$   rC   )r"   r   s     r#   save_import_reportImportUtils.save_import_report5  se    
 II##%"	
 	%!"$	

 
s   0A
A)c                   [        5         [        S5        [        S5        [        S5        [        5         [        SU R                  R                   35        [        SU R                  R                   35        [        SU R                  R                   35        [        SU R                  R
                   35        [        SU R                  R                   35        [        SU R                  R                   35        [        S	U R                  R                   35        [        S
U R                  R                   35        [        SU R                  R                   35        [        S[        U R                  R                  5       35        [        S[        U R                  R                  5       35        [        5         [        S5        [        5         g )Nro   zLeafDoctor AI Import SummaryzMaster Labels         : zTreatment Records     : zImported Labels       : zImported Treatments   : r   r   r   r   r   zWarnings              : zErrors                : )rC   r5   r   r   r   r   r   r   r   r   r   rF   r   r   r!   s    r#   print_summaryImportUtils.print_summaryM  s   h,-h&{{(()+	

 	&{{,,-/	

 	&{{**+-	

 	&{{../1	

 	&{{++,.	

 	&{{../1	

 	&{{++,.	

 	&{{++,.	

 	&{{''(*	

 	&4;;''()+	

 	&4;;%%&')	

 	hr&   c                D   U R                  5         U R                  5         U R                  5         U R                  5         U R	                  5         U R                  5         U R                  5         U R                  5         U R                  5         U R                  5         g)z
Complete import workflow.
N)
rq   rG   r^   rh   r   r   r   r   r   rt   r!   s    r#   
run_importImportUtils.run_import  sy    
 	  "((*!r&   )r9   r4   r6   r8   r5   r7   N)r4   r   )rf   r   )r(   r)   r*   r+   r:   rG   staticmethodrS   rW   r^   rh   rl   rq   rt   r   r   r   r   r   r   r   r   r   r   r   r   r.   r'   r&   r#   r0   r0   l   s    6$
<    	 	#
R4&3

SrC7R*2`(\8/.jR*p#(RG
Z
0GZr&   r0   )__doc__
__future__r   r   dataclassesr   r   pathlibr   typingr   r   r	   r
   pandasrA   sqlalchemy.ormr   configr   modelsr   r   	data_pathr=   r@   r   r   r   r0   r'   r&   r#   <module>r      s   $ #  (  , ,  "  ">>
 ,-      &
 &
 &
\E Er&   