
    ג[i               	          d Z ddlZddl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 ddlmZ ddlmZ dd	lmZ 	 d#d
edeeef         ddfdZd Zde
deeef         fdZ	 d#d
ede
defdZ	 d#d
ede
defdZdefdZdeeef         defdZdeeef         defdZdeeeef                  defdZdedej        deeeef                  defdZ deeef         defdZ!deeef         fd Z"d!eeef         defd"Z#dS )$at  
JSON vs DB Comparison Tab

This tab provides a visual comparison interface between JSON files and MongoDB records.
Users can review differences, make import decisions, and manually apply imports.

Key features:
- Load JSON from ODF directory structure
- Compare with MongoDB records
- Visual diff display with color coding
- Manual import decisions
- No automatic writes
    N)DictAnyList)
JSONLoader)
DiffEngine)ImportPreviewEngine)UpdateEngine)DataService)ObjectIddata_serviceconfigreturnc                    |d         d         }t          j        d           t          j        d           |                                 st          j        d           dS t          ||d                   }t          |d                   }t                      }t                       t          j        d           t          | ||           t          j        d           t           j
                            d	          r2t           j
                            d
          rt          | ||||           t           j
                            d          r&t          j        d           t          ||            dS dS )z
    Render the JSON vs DB comparison tab.
    
    Args:
        mongo_service: MongoService instance
        data_service: DataService instance
        config: Application configuration dictionary
    json_sources	base_pathu   🔄 JSON vs MongoDB Comparisona  
    Compare JSON files with MongoDB records and manually import selected data.
    
    **Workflow:**
    1. Select collection and JSON source
    2. Load and compare data
    3. Review differences
    4. Make import decisions
    5. Apply selected imports
    u7   ❌ Not connected to MongoDB. Please check the sidebar.Ncollections---comparison_collectioncomparison_sourcecomparison_results)sttitlemarkdownis_connectederrorr   r   r   _init_comparison_state_render_selection_panelsession_stateget_render_load_panel_render_results_panel)mongo_servicer   r   settings_servicejson_base_pathjson_loaderdiff_enginepreview_engines           ./var/www/html/IGF-ODF-V3/ui/tabs/json_vs_db.pyrender_json_vs_db_tabr)      s    N+K8NH.///K 	 		 		 		 %%'' 
JKKK ^VM-BCCKVM233K(**N K M;???K 
344 
9I9M9MNa9b9b 
	
 	
 	
 
011 =
Enm<<<<<= =    c                  ~   dt           j        vrdt           j        _        dt           j        vrdt           j        _        dt           j        vrdt           j        _        dt           j        vrdt           j        _        dt           j        vrdt           j        _        dt           j        vrd	t           j        _        dS dS )
z,Initialize session state for comparison tab.r   Nr   r   comparison_loadedFlast_comparison_keydata_editor_keyr   )r   r   r   r   r   r,   r-   r.    r*   r(   r   r   Z   s    b&66 615.""22 2-1*2#33 3.2+""22 3-2*B$44 4/3, 00 -+,(((- -r*   r%   c                 j   t          j        d           t          j        d          \  }}|5  |                                }|r*t          j        d|dd          }|t           j        _        n/t          j        d|j                    dt           j        _        d}ddd           n# 1 swxY w Y   |5  |d	         }d
 |	                                D             }|r9g }	|D ]3}
|
                    |
|          }|dk    r|	                    |
           4ng }	|	rdt          j        d|	dd          }|t           j        _        |                    |          }|d         rt          j        d|d                     n-|rt          j        d| d           dt           j        _        d}ddd           n# 1 swxY w Y   | dt           j        j         }t           j        j        |k    r3dt           j        _        dt           j        _        |t           j        _        |r	t           j        j        r|                    |t           j        j                  }|d         rt          j        d          \  }}}|5  t          j        d|d                    ddd           n# 1 swxY w Y   |5  t          j        d|d                    ddd           n# 1 swxY w Y   |5  |                     |          }t          j        d|d           ddd           dS # 1 swxY w Y   dS dS dS dS )z
    Render collection and source selection panel.
    
    Args:
        mongo_service: MongoService instance
        json_loader: JSONLoader instance
        config: Application configuration dictionary
    u$   1️⃣ Select Source and Collection   zJSON Sourcecomparison_source_selectorz;Select JSON source directory (e.g., tokyo_2020, paris_2024))optionskeyhelpu    ⚠️ No JSON sources found in Nr   c                 p    g | ]3\  }}|                     d d          |                     dd          1|4S )enabledTallow_manual_importFr   ).0namecoll_configs      r(   
<listcomp>z+_render_selection_panel.<locals>.<listcomp>   sX     
 
 
&T;y$//
4?OODY[`4a4a

 
 
r*   r   
Collectioncomparison_collection_selectorzGSelect a collection (only showing collections with data in this source)validation_enabled   📋 descriptionu$   ⚠️ No collections with data in ``_F	supported   z
ODF Folderfolderz
JSON Files
file_countzMongoDB Docs,)r   	subheadercolumnsget_available_sources	selectboxr   r   warningr   itemscount_files_in_sourceappendr   get_validation_infoinfor-   r   r,   get_collection_infometriccount_documents)r"   r%   r   col1col2available_sourcesselected_sourcecollections_configall_collectionsavailable_collections	coll_namerH   selected_collectionvalidation_infocurrent_keyrS   col3db_counts                     r(   r   r   o   s    L7888AJD$	 # #'==?? 	# l)0R	  O 2AB..JQ+:OQQRRR15B."O# # # # # # # # # # # # # # #" 
 %' %'#M2
 
*<*B*B*D*D
 
 
  	'$&!, < <	(>>y/ZZ
> <)00;;;<
 %'!  	'"$,-4^	# # # 6IB2 *==>QRRO34 B@ >@@AAA V
T/TTTUUU59B2"&K%' %' %' %' %' %' %' %' %' %' %' %' %' %' %'P )OO2+;+MOOK	+{: ;.2+-2*/:,  ;r/A ;...
 

  	;!z!}}D$ 8 8	,X7778 8 8 8 8 8 8 8 8 8 8 8 8 8 8  < <	,\(:;;;< < < < < < < < < < < < < < <  ; ;(889LMM	.X//:::; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ;	; 	;s[   A0B**B.1B.7C7F::F>F>>J&&J*-J*3KK"K(-L""L&)L&r&   c                 F   t          j        d           t          j        ddg          \  }}|5  t          j        d           ddd           n# 1 swxY w Y   |5  t          j        ddd	          rt          | ||||           ddd           dS # 1 swxY w Y   dS )
a  
    Render load and compare panel.
    
    Args:
        mongo_service: MongoService instance
        data_service: DataService instance
        json_loader: JSONLoader instance
        diff_engine: DiffEngine instance
        settings_service: SettingsService instance (optional)
    u   2️⃣ Load and ComparerF      zFClick 'Load & Compare' to analyze differences between JSON and MongoDBNu   🔄 Load & Compareload_compare_btnprimaryr4   type)r   rJ   rK   rS   button_perform_comparison)r"   r   r%   r&   r#   rW   rX   s          r(   r    r       sZ   " L+,,,QF##JD$	 Z Z
XYYYZ Z Z Z Z Z Z Z Z Z Z Z Z Z Z 
  9!"
 
 
 	
                      s#   AAA+BBBc                    t           j        j        }t           j        j        }t          j        d          5  |                    ||          }|rt          d |D                       }t          |          dk    r9t          j        d|            t          j        d           	 ddd           dS ||vr-t          j	        d|
                                 d| d	           d
}	|r|                                }	|                    ||	          }
ddd           n# 1 swxY w Y   t          j        d          5  |                    |||
          }ddd           n# 1 swxY w Y   d}|r|                    |          }|rkt          j        d          5  ddlm} ddlm}  |t           j        j                  }|}|                    |||          }ddd           n# 1 swxY w Y   |t           j        _        |t           j        _        dt           j        _        t           j        xj        dz  c_        dt           j        v rt           j        `dt           j        v rt           j        `t                      }|D ]3}|                    d |                                D                        4|r|d                             d|          n|}t=          d |D                       }|                    |          }|                    dd          }|d                             dd          }|d                             dd          }|                    dg           }t          j         d!                    g d| d| d |rd!!                    |          nd" d#| d$|d%          d&| d'd!!                    |d(                    d)|rd!!                    |          nd* d+|d%         d,d-|d.         d,d/|d         d0         d,d1|d         d2         d,d3| d4| d5|d         d6         d,d7|d         d8         d,d9t          |          d,d:                     |rf|d         }|d;         dk    r(t          j        d<|d=         d,d>|d?         d,d@|d;         d,dA|dB          dC	           t          j"        dDdE          5  tG          |dF         d          D ]\  }}|dG         }|dH         }|                    dI|                    dJdK|                     }t          j$        dL| dM| dN           |D ]1} t          j        dO| dP          dQ| dR          dS| dT                     2t          j$        dU           	 ddd           n# 1 swxY w Y   nTt          j         dV|d=         d,dA|dB          dW           n+|r)|                    |          rt          j%        dX           t          j"        dYdZE          5  t          j$        d[           t          j&        d\t          |                      t          j&        d]t          |
                      t          j&        d^|
r1tO          d_ |
d                                         D                       nd`            |rgt          j$        da           db |d                                         D             ddc         }!t          j(        d!!                    |!                     |
rgt          j$        dd           de |
d                                         D             ddc         }"t          j(        d!!                    |"                     t          j$        df           t          j&        dg|d(                     t          j&        dh|            t          j&        di|            |rs|d(         rkt          j$        dj           |d         }#t          j&        dk           |d(         D ]2}$|#                    |$dl          }%t          j&        dm|$ dn|%            3|
r_|d(         rWt          j&        do           |
d         }&|d(         D ]2}$|&                    |$dl          }%t          j&        dm|$ dn|%            3ddd           n# 1 swxY w Y   |dpk    rI|rGt          j%        dqd!!                    |d(                    drd!!                    |           ds           ||d%         k     rt          j	        dt           t          j)                     dS )uz
    Perform the comparison between JSON and MongoDB.
    
    Args:
        mongo_service: MongoService instance
        data_service: DataService instance
        json_loader: JSONLoader instance
        diff_engine: DiffEngine instance
    zLoading data...c              3   @   K   | ]}|                     d           V  dS )_target_collectionNr9   r:   rs     r(   	<genexpr>z&_perform_comparison.<locals>.<genexpr>  s/      $W$WQQUU+?%@%@$W$W$W$W$W$Wr*   re   u7   ⚠️ ERROR: Mixed collections detected in JSON data: zBThis should not happen. Each collection must be loaded separately.Nu8   ⚠️ WARNING: JSON records are marked for collection 'z' but you selected ''i  )limitzComparing records...z'Validating foreign key relationships...r   )ForeignKeyValidator)MongoServiceTnew_records_preview_dfupdate_preview_dfc              3   D   K   | ]}|                     d           |V  dS )rD   N
startswithr:   ks     r(   rq   z&_perform_comparison.<locals>.<genexpr>T  s3      QQQq||C?P?PQqQQQQQQr*   rn   c              3   F   K   | ]}|                     d d          dV  dS _validation_passedFre   Nr9   ro   s     r(   rq   z&_perform_comparison.<locals>.<genexpr>Z  s7      !`!`QUUCWY^=_=_!`!!`!`!`!`!`!`r*   matching_strategyprimary_onlysummaryprimary_key_matchesalternative_key_matchesalternative_keys uD   
    ✅ **Comparison Complete**
    
    - **Target Collection:** `z`
    - **JSON Source:** `z%`
    - **Expected Document Types:** , r   z
    - **Validation:** /
json_countzG records passed document type validation
    - **Matching Strategy:** `z`
    - **Primary Keys:** matching_keysz
    - **Alternative Keys:** Nonez
    - JSON Records: rI   z
    - MongoDB Records: rc   z
    - Exact Matches: exact_match_countz
    - Duplicates: duplicate_countz (Primary: z, Alternative: z)
    - New Records: new_record_countz
    - New Fields: new_field_countz
    - Total JSON Fields: z# (all nested fields flattened)
    invalid_countui   
            ❌ **Foreign Key Validation Failed**
            
            - **Total Records Checked:** total_recordsz"
            - **Valid Records:** valid_countz$
            - **Invalid Records:** z)
            - **Foreign Keys Checked:** foreign_keys_checkedur   
            
            ⚠️ Some records have invalid foreign key references. See details below.
            u"   ❌ Invalid Foreign Key References)expandedinvalidrecorderrorscodeidRecord #z**z. Record: `z`**u   ❌ Field `fieldz` = `valuez`: r   r   uc   
            ✅ **Foreign Key Validation Passed**
            
            - **Records Checked:** zL
            
            All foreign key references are valid!
            uB   ℹ️ Foreign key validation is configured but was not performed.u   🔍 Debug InformationFz### Data Loading DetailszJSON records loaded: zMongoDB records loaded: zMongoDB records are flattened: c              3      K   | ]}d |v V  	dS ).Nr/   r{   s     r(   rq   z&_perform_comparison.<locals>.<genexpr>  s&      5]5]1cQh5]5]5]5]5]5]r*   N/Az+### Sample JSON Record Keys (first record):c                 <    g | ]}|                     d           |S rD   ry   r{   s     r(   r=   z'_perform_comparison.<locals>.<listcomp>  s*    [[[aVYIZIZ[[[[r*      z.### Sample MongoDB Record Keys (first record):c                 <    g | ]}|                     d           |S r   ry   r{   s     r(   r=   z'_perform_comparison.<locals>.<listcomp>  s*    WWWAQ\\RUEVEVWaWWWr*   z### Business Key MatchingzPrimary keys configured: zAlternative keys configured: zMatching strategy: z### Sample Business Key ValueszFrom first JSON record:z	NOT FOUNDz  : zFrom first MongoDB record:primary_or_alternativeu\   💡 **Multi-Key Matching Enabled:**
        - System first tries to match by primary keys: z0
        - If no match, tries alternative keys: zj
        - This allows matching athletes across different competitions even if their codes differ
        uc   ⚠️ Note: Some files were skipped due to document type mismatch. Check console logs for details.)*r   r   r   r   spinnerload_collection_from_sourcesetlenr   rN   popget_record_limitload_flattened_recordscompare_collectionsget_foreign_keysservices.foreign_key_validatorrt   services.mongoru   r"   validate_foreign_keysr   fk_validation_resultsr,   r.   rv   rw   updatekeysr   sumget_expected_document_typessuccessjoinexpander	enumerater   rS   textanyr   rerun)'r"   r   r%   r&   r#   collection_namesource_namejson_recordstarget_collectionsrecord_limit
db_recordsresultsr   foreign_keysrt   ru   fk_validatorall_records_to_validateall_json_fieldsr   target_collectionvalidation_passed_countexpected_typesr   primary_matchesalt_matchesr   
fk_summaryidxitemr   	record_idr   sample_json_keyssample_db_keyssample_jsonr4   r   	sample_dbs'                                          r(   rk   rk      s     &<O"4K	%	&	& 
 
">>
 
  		X!$$W$W,$W$W$W!W!W%&&* gSegghhh]^^^
 
 
 
 
 
 
 
  &88 X
  WVhVlVlVnVn  W  W  ET  W  W  W  X  X  X  	?+<<>>L!88 9 
 

3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
< 
*	+	+ 
 
11
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 ! '88II 	EFF  NNNNNN7777772223C3QRR +7'(4(J(J#+ ) )%               +2B'-BB*)-B& $$)$$  2#33 43b.. /. eeO R RQQ&++--QQQQQQQ WcwQ++,@/RRRhw "!`!`\!`!`!``` !<<=NOON  $7HHi(,,-BAFFO)$(()BAFFK{{#5r::J        1    %	   
 BP$ZDIIn$=$=$=UZ    /    291F     1    7?#;<<    =MXTYY'7888RX    \*      
+     i()<=     9%&78     HW    hs    I&'9:     9%&78      o..!       	 	 	(  %V*95
o&* !	H 	 +5_*E	 	 	 #-]";		 	 	
 %/$?	 	 	 *44J)K	 	 	 	 	 	 ADQQQ ' '!*+@+KQ!O!O 
' 
'IC!(^F!(^F &

66::dDTsDTDT3U3U V VIK CS C CY C C CDDD!' i i!guW~!g!gE'N!g!gW\]dWe!g!ghhhhK&&&&
'' ' ' ' ' ' ' ' ' ' ' ' ' ' ' J  %/$?   *44J)K	       
 V.??PP V
TUUU 
-	>	>	> "- "-
.///
;L(9(9;;<<<
<3z??<<===
xak2v#5]5]
STHZHZH\H\5]5]5]2]2]2]qvxxyyy 	1KEFFF[[<?+?+?+A+A[[[\_]_\_`GDII.//000 	/KHIIIWWA););)=)=WWWX[Y[X[\NGDIIn--...
/000
FGO,DFFGGG
B0@BBCCC
9&799::: 	-GO4 	-K8999&q/KG-.../ - -#[99+S++E++,,,, 	-'/2 	-G0111"1I/ - -!c;77+S++E++,,,,E"- "- "- "- "- "- "- "- "- "- "- "- "- "- "-J 44 9I 
 8<		'/BZ8[8[ 04		:J0K0K   	 	 	 !66 {

yzzzHJJJJJsd   A1D!5A D!!D%(D% E$$E(+E(A G**G.1G.1B=V;;V?V?1J.c++c/2c/r'   c                    t           j        j        }t          j        d           t          j        d          \  }}}}|5  t          j        d|d         d         d           ddd           n# 1 swxY w Y   |5  t          j        d	|d         d
         |d         d
         dd           ddd           n# 1 swxY w Y   |5  t          j        d|d         d         |d         d         dd           ddd           n# 1 swxY w Y   |5  t          j        d|d         d         d           ddd           n# 1 swxY w Y   t          j        d           t          j        d|d         d          dd|d         d
          dd|d         d          dd|d         d          dg          \  }}}	}
|5  t          ||            ddd           n# 1 swxY w Y   |5  t          || |           ddd           n# 1 swxY w Y   |	5  t          || |           ddd           n# 1 swxY w Y   |
5  t          |           ddd           dS # 1 swxY w Y   dS )z
    Render comparison results with tabs.
    
    Args:
        preview_engine: ImportPreviewEngine instance
        mongo_service: MongoService instance
    u   3️⃣ Review Differences   zExact Matchesr   r   zRecords that are identicalr5   N
Duplicatesr   normalz8Records with matching business keys but different values)deltadelta_colorr5   zNew Recordsr   zRecords not found in MongoDB
New Fieldsr   zFields in JSON not in MongoDBr   u   ✅ Exact Matches ()u   ⚠️ Duplicates (u   🆕 New Records (u   📋 New Fields ()r   r   r   rJ   rK   rU   r   tabs_render_exact_matches_tab_render_duplicates_tab_render_new_records_tab_render_new_fields_tab)r'   r"   r   rW   rX   rb   col4tab1tab2tab3tab4s              r(   r!   r!     s    1GL-...  Z]]D$d	 
 

	I23-	
 	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

	I01)$%67 K	
 	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

	I12)$%78 /	
 	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

	I010	
 	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 K  WHgi01DEHHHFgi01BCFFFFWY/0BCFFFDGI./@ADDD	&  D$d 
 ; ;!'>:::; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 
 G GwFFFG G G G G G G G G G G G G G G 
 H HGGGH H H H H H H H H H H H H H H 
 ( (w'''( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (s   $A11A58A5>2B<<C C 	2DDD$EEEGG#&G#,H

HHH55H9<H9II#&I#r   c                    | d         }|st          j        d           dS t          d |D                       }t          j        dt	          |           d           |t	          |          k    rt          j        d           t          j        d           |                    |d	          }|j        s|                    d
 |j	        D             d          }t          j        dt	          |           dt	          |j	                   d           t          j        d           t          j
        |ddd           dS dS )z%Render exact matches tab (read-only).exact_matchesu   ℹ️ No exact matches foundNc              3   F   K   | ]}|                     d d          dV  dS r~   r9   ro   s     r(   rq   z,_render_exact_matches_tab.<locals>.<genexpr>#  s7      YYaee<PRW6X6XY!YYYYYYr*   u   ✅ z* records are identical in JSON and MongoDBu/   ✅ All records passed document type validationu   
    These records are already in MongoDB and match exactly.
    **No action needed.**
    
    🟠 **Orange background** = These values exist in MongoDB (identical to JSON)
    exactc                 <    g | ]}|                     d           |S r   ry   r:   cs     r(   r=   z-_render_exact_matches_tab.<locals>.<listcomp>6  s)    %Q%Q%QAq||C?P?P%Qa%Q%Q%Qr*   ignore)rK   r      📊 Displaying  records with z% fields (all nested fields flattened)u<   **🟠 These values are identical in both JSON and MongoDB**stretchT  width
hide_indexheight)r   rS   r   r   r   r   build_preview_dataframeemptydroprK   	dataframe)r   r'   r   validated_countdf
display_dfs         r(   r   r     s   O,M 
/000 YY]YYYYYOJTc-((TTTUUU#m,,, D
BCCCK  	 	 	 
	/	/w	G	GB8 
WW%Q%Q%Q%Q%QZbWcc

  A3z??  A  A#jFXBYBY  A  A  A  	B  	B  	B
RSSS
		
 	
 	
 	
 	
 	

 
r*   c                    | d         }|st          j        d           dS t          d |D                       }t          d |D                       }t          d |D                       }t          j        dt	          |           d           |t	          |          k    rt          j        d	           n(t          j        d
| dt	          |           d           |dk    rbt          j        d| dd                    | d                    d| dd                    |                     dg                      d	           n1t          j        dd                    | d                    d           t          j        d           t          j        d           t          |          D ]\  }}|                    dd          }	|                    dd          }
|	dk    rdnd }|	dk    rd!nd"}t          j	        | d#|d$z    d%| d&|
           5  t          j
        d'|            t          j
        d(|
            ddd           n# 1 swxY w Y   t          j        d)           |                    |          j        sfd*}t          j        d+           j                            |d$,          }t          j        d-t	                     d.           t          j        |d/d0d12           t          j        d3           t          j        d)           t!          || d4         |           dS dS )5z+Render duplicates tab with comparison view.
duplicatesu   ℹ️ No duplicates foundNc              3   R   K   | ]"}|d                               dd          dV  #dS json_recordr   Fre   Nr9   r:   ds     r(   rq   z)_render_duplicates_tab.<locals>.<genexpr>Q  s>      ee1]3C3G3GH\^c3d3de!eeeeeer*   c              3   L   K   | ]}|                     d           dk    dV   dS )match_methodprimary_keyre   Nr9   r  s     r(   rq   z)_render_duplicates_tab.<locals>.<genexpr>T  s8      ZZ1553H3HM3YZ!ZZZZZZr*   c              3   L   K   | ]}|                     d           dk    dV   dS )r  alternative_keyre   Nr9   r  s     r(   rq   z)_render_duplicates_tab.<locals>.<genexpr>U  s9      ZZAquu^/D/DHY/YZaZZZZZZr*      ⚠️ z potential duplicate(s) foundu9   ✅ All duplicate records passed document type validation   ⚠️ Only r   z duplicates passed validationr   u"   🔍 **Match Methods:**
        - z matched by primary keys: r   r   z
        - z matched by alternative keys: r   u   
        
        💡 Alternative key matches allow finding the same athlete across different competitions 
        even when their athlete code differs.
        z1
        These records match by business keys: **z**
        u9  
    **Update Workflow:**
    1. Review field-by-field comparison below
    2. Select which fields to update (✅ Update or ❌ Skip)
    3. Apply updates to MongoDB
    
    💡 **Use Case:** When athlete info changes (name, birthdate, nationality), 
    you can selectively update only the changed fields.
    z### Duplicate Recordsr  unknownmatching_keyr   r	  u   🔑u   🔍zPrimary KeyzAlternative Keyz Duplicate #re   z - Matched by r   zMatch Method: zMatching Values: r   c                    g }t          j                  D ]\  }}|dk    r|                    d           !|dk    r|| d         dk    r|                    d           I| d         dk    r|                    d           k| d         dk    r|                    d	           |                    d           |d
k    r|                    d           |dk    r|                    d           |                    d           |S )Nr   r   statusnewz,background-color: #90EE90; font-weight: bold	differentz,background-color: #FFD700; font-weight: boldmissing_in_jsonz,background-color: #FFB6C1; font-weight: bold
json_valuez9background-color: #E3F2FD; border-left: 3px solid #2196F3db_valuez9background-color: #FFF3E0; border-left: 3px solid #FF9800)r   rK   rQ   )rowstylesr   colcomp_dfs       r(   highlight_comparisonz4_render_duplicates_tab.<locals>.highlight_comparison  s=   F%go66 & &S'> &MM"%%%%H_ &8}- *&TUUUUX+5 *&TUUUUX*;; *&TUUUUb))))L( &MM"]^^^^J& &MM"]^^^^MM"%%%%Mr*   z### Field-by-Field Comparison)axisr   z- field comparisons with full nested structurer   Tr   r   u  
        **Color Legend:**
        - 🟢 **Green** = New field in JSON (not in MongoDB)
        - 🟡 **Yellow** = Different values between JSON and MongoDB
        - 🔴 **Pink** = Field exists in MongoDB but missing in JSON
        - 🔵 **Blue background** = Value from JSON file
        - 🟠 **Orange background** = Value from MongoDB
        - ⚪ **White** = Matching values
        r   )r   rS   r   rN   r   r   r   r   r   r   r   $build_duplicate_comparison_dataframer   styleapplyr   _render_update_controls)r   r'   r"   r  r   r   r   r   dupr  r  
match_iconmatch_labelr  	styled_dfr  s                  @r(   r   r   D  s@    &J 
,--- eeZeeeeeO ZZZZZZZZOZZZZZZZKJGZGGGHHH#j//) d
LMMMM

b/bbC
OObbbccc Q 
  6:ii@X6Y6Y  6:iiL^`b@c@c6d6d   	 	 	 	 	 157?;S1T1T   	 	 	 K  	 	 	 K'(((j)) 	8 	8Sww~y99ww~u55+}<HVV&
'3}'D[mmJ[[JhhC!Ghh;hhZfhhii 	8 	8G2[22333G666777	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 K AA*MMG= :
	 	 	 	 	0 	3444 M''(<1'EE	
^3w<<^^^___
		
 	
 	
 	
 	  	 	 	 	E 	 %&	
 	
 	
 	
 	
m:
 :
s   /II	I	r  r   c                 
   t          j        d           t          j        d           t                      }dt           j        vr$|                    |           t           j        _        t           j        j        }|j        rt          j        d           dS t          j        g d          \  }}}}}	|5  t          j	        ddd	
          r:|
                    |dg          t           j        _        t          j                     ddd           n# 1 swxY w Y   |5  t          j	        ddd
          r:|
                    |dg          t           j        _        t          j                     ddd           n# 1 swxY w Y   |5  t          j	        ddd
          r7|                    |          t           j        _        t          j                     ddd           n# 1 swxY w Y   |	5  t          j	        ddd
          r7|                    |           t           j        _        t          j                     ddd           n# 1 swxY w Y   t          j        d           |                    |          }
t          j        d          \  }}}}|5  t          j        d|
d                    ddd           n# 1 swxY w Y   |5  t          j        d|
d                    ddd           n# 1 swxY w Y   |5  t          j        d|
d                    ddd           n# 1 swxY w Y   |5  t          j        d|
d                     ddd           n# 1 swxY w Y   t          j        d           t          j        d!           t          j        d"           t          j        |d#d$d%d&t           j                            d'd$d()          t           j                            d*d$d()          t           j                            d+d$d,)          t           j                            d-d$d()          t           j                            d.d$d,)          t           j                            d/d$d,)          t           j                            d0d1d2gd$d3d(4          d5d6t           j        j         7          }|t           j        _        |
d         d8k    rt          j        d           t          j        d9|
d          d:|
d          d;           t          j        d<d=g          \  }}|5  t          j	        d>d?d@A          rt/          ||| ||           ddd           dS # 1 swxY w Y   dS dS )Bz
    Render update controls for selective field updates.
    
    Args:
        duplicates: List of duplicate records
        collection_name: Name of the collection
        mongo_service: MongoService instance
    u   🔄 Selective Field Updatesu   
    💡 **How it works:**
    - Select which fields you want to update in MongoDB
    - New fields are selected by default
    - Different fields require your decision
    - Matching fields are skipped by default
    rw   u   ℹ️ No fields to updateN)r1   re   re   re   re   u   ✅ Update New Fieldsupdate_new_fieldszMark all new fields for update)r4   r5   r  )status_filteru   ✅ Update Differentupdate_different_fieldsz$Mark all different fields for updater  u   ❌ Skip Allskip_all_updateszSkip all updates
   🔄 Resetreset_update_decisionszReset to defaultsr   r   zRecords to Updaterecords_to_updatezFields to Updatefields_to_updater   
new_fieldszDifferent Fieldsdifferent_fieldsz### Select Fields to UpdateuR  
    **Color Legend:**
    - 🟢 **Green** (new) - Field exists in JSON but not in MongoDB
    - 🟡 **Gold** (different) - Field value differs between JSON and MongoDB
    - 🟣 **Pink** (missing_in_json) - Field exists in MongoDB but not in JSON
    - 🔵 **Light Blue** - JSON value
    - 🟠 **Light Orange** - MongoDB value
    r   Tfixedr   r   small)disabledr   zDB IDz
Field NamemediumStatusz
JSON ValuezMongoDB ValueActionskipr   z#Choose whether to update this fieldr3   requiredr5   r   )_record_index_db_idr   r  r  r  _update_decisionupdate_preview_editor_r   r   num_rowsr   column_configr4   r   u   ⚠️ Ready to update z record(s) with z	 field(s)rF   re   u   🚀 Apply Updatesapply_updates_btnrg   rh   )r   rJ   rS   r	   r   build_update_preview_dataframerw   r   rK   rj   mark_all_for_updater   mark_all_for_skipr   get_update_summaryrU   data_editorr?  NumberColumn
TextColumnSelectboxColumnr.   rN   _apply_field_updates)r  r   r"   update_enginer   rW   rX   rb   r   col5r   	edited_dfs               r(   r   r     se    L/000G  	 	 	 !NNM ""22 f-:-Y-YZd-e-e*			+B	x 
,--- $&:ooo#>#> D$dD	  9,2ELlmmm 	1>1R1RSUfkel1R1m1mB.HJJJ              
 
  9+1JQwxxx 	1>1R1RSUfqer1R1s1sB.HJJJ              
 
  9^);BTUUU 	1>1P1PQS1T1TB.HJJJ              
 
  9\'?FYZZZ 	1>1]1]^h1i1iB.HJJJ              
 K ..r22GZ]]D$d	 E E
	%w/B'CDDDE E E E E E E E E E E E E E E 
 C C
	$g.@&ABBBC C C C C C C C C C C C C C C 
 7 7
	, 56667 7 7 7 7 7 7 7 7 7 7 7 7 7 7 
 C C
	$g.@&ABBBC C C C C C C C C C C C C C C K K-... K  	 	 	 
-:: ;  
 &11 2  
 %00 1  
 &11 2  
 *55 6  
 (33 4  
 !# 0 @ @*: !A ! !?&
 &
N HR%5%EGG[. . .Ib *3B& !"Q& 
E

  BW5H-I  B  B[bcu[v  B  B  B  	C  	C  	CZA''
d 	 	y$'   
 %#!!  	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 s   5ADDD AE>>FFAG&&G*-G*3AIIIKK	K	K::K>K>L//L36L3<M$$M(+M(7+U//U36U3
preview_dfrJ  c                    t          j        d           |                    |          }t          j        d|d          d|  d|d          d|d          d	|d
          d           t          j        d          \  }}|5  t          j        dddd          r\|                    ||          }|s"t          j        d           	 ddd           dS |                    |           }	|	r	 t          j	        dt          |           d          5  d}
g }|D ]}	 dt          |d         d                   i}|	                    ||d                   }|j        dk    r|
dz  }
M# t          $ r8}|                    d|d          dt!          |                      Y d}~d}~ww xY w	 ddd           n# 1 swxY w Y   |
dk    rt          j        d|
 d|  d            |rIt          j        d!t          |           d"           |dd#         D ]}t          j        d$|            dt           j        _        dt           j        _        d%t           j        _        t          j        d&           n/t          j        d'           |r|D ]}t          j        |           nO# t          $ r.}t          j        d(t!          |                      Y d}~nd}~ww xY wt          j        d)           ddd           n# 1 swxY w Y   |5  t          j        d*d+d,          r't          j        d-           t          j                     ddd           dS # 1 swxY w Y   dS ).a2  
    Apply selected field updates to MongoDB.
    
    Args:
        collection_name: Name of collection
        preview_df: Preview DataFrame with update decisions
        duplicates: Original duplicate records
        update_engine: UpdateEngine instance
        mongo_service: MongoService instance
    z### Confirm Updatesu&   
    ⚠️ **You are about to update r,  z record(s) in z+**
    
    This action will:
    - Update r-  z field(s) in MongoDB
    - Preserve all other fields unchanged
    - Cannot be undone automatically
    
    **Fields to update:**
    - New fields: r.  z
    - Different fields: r/  z
    r1   u   ✅ Confirm Updatesconfirm_updates_btnrg   r   r4   ri   r   u#   ❌ No update operations to performNz	Updating z record(s)...r   _idfilterr   re   zRecord record_indexr   u   ✅ Successfully updated z record(s) in collection: `rC   r  z update(s) failed:   z  - F1   💡 Reload the comparison to see updated resultsu   ⚠️ No records were updatedu   ❌ Failed to update: u   ❌ Collection not found
   ❌ Cancelcancel_updates_btnr4   r   zUpdates cancelled)r   r   rD  rN   rK   rj   prepare_update_operationsr   get_collectionr   r   r   
update_onemodified_count	ExceptionrQ   strr   r   r   rw   r   r,   rS   r   )r   rM  r  rJ  r"   r   rW   rX   
operations
collectionupdated_countr   opfilter_dictresulter   s                    r(   rI  rI  m  s&   " K%&&& ..z::GJ &-.A&B Ra  ()	  <(  !!34   	 	 	 AJD$	 95 959!%	
 
 
 8	5 '@@ZXXJ >???95 95 95 95 95 95 95 95 '55oFFJ (5%@$NJ$N$N$NOO X X()!#", X XBX/4hr(|E?R6S6S.T)3)>)>{BxL)Y)Y#)#81#< !7$1Q$6M#, X X X &.V>8J.V.VcRSff.V.V W W W W W W W WXXX X X X X X X X X X X X X X X %q( 0
#{}#{#{ix#{#{#{|||! 8J'PV'P'P'PQQQ)/ 8 8 "u 7 7 7 7 >B(:>B(;=B(: STTTT
#CDDD! 0)/ 0 0 "  @ @ @H>c!ff>>????????@ 3444s95 95 95 95 95 95 95 95 95 95 95 95 95 95 95v 
  9$
 
 
 	
 G'(((HJJJ                 s   ?ALL,%J&	F7A	E%$F7%
F'	/.F"	F7"F'	'F7+J&7F;	;J&>F;	?C&J&%L&
K0$KLKLLL?MM!Mc           
         | d         }|st          j        d           dS |r"|d         d                             dd          nd}t          d |D                       }t          j        d	t          |           d
| d           |t          |          k    rt          j        d| d           n(t          j        d| dt          |           d           t          j        d           dt           j        vr%|	                    |d          t           j        _
        t           j        j
        }|j        rdS t          j        g d          \  }}}	}
|5  t          j        ddd          r7|                    |          t           j        _
        t          j                     ddd           n# 1 swxY w Y   |	5  t          j        dd          r7|                    |          t           j        _
        t          j                     ddd           n# 1 swxY w Y   |
5  t          j        dd          r8|	                    |d          t           j        _
        t          j                     ddd           n# 1 swxY w Y   t          j        d           d |j        D             }t          j        d t          |           d!t          |           d"           t           j                            d#g d$d%d&d'(          t           j                            d)d%d*d'+          d,}|j        D ]}|                    d-          s||         j        }|d.v r%t           j                            |d/0          ||<   M|d1k    r%t           j                            |d20          ||<   xt           j                            |d30          ||<   t          j        |dd%d4d5|d6t           j        j         7          }|t           j        _
        |                    |          }t          j        d8           t          j        d9          \  }}}	|5  t          j        d:t          |d;                              ddd           n# 1 swxY w Y   |5  t          j        d<t          |d=                              ddd           n# 1 swxY w Y   |	5  t          j        d>t          |d?                              ddd           n# 1 swxY w Y   t          |d;                   dk    rt          j        d           t          j        d@t          |d;                    dA           dBt           j        vrdt           j        _        t          j        d9dCg          \  }}|5  t          j        dDdEdF          r5| dG         |d;         ||dHt           j        _        t          j                     ddd           n# 1 swxY w Y   t           j        j        $t;          t           j        j        ||           dS dS dS )Iz,Render new records tab with import controls.new_recordsu   ℹ️ No new records foundNr   r  rn   r  c              3   R   K   | ]"}|d                               dd          dV  #dS r  r9   ro   s     r(   rq   z*_render_new_records_tab.<locals>.<genexpr>  s>      hh!a6F6J6JK_af6g6ghAhhhhhhr*   u   🆕 z0 new record(s) ready for import to collection: `rC   u   ✅ All z( records passed document type validationr  r   z records passed validationu  
    These records are not in MongoDB. You can:
    - Review and edit the data
    - Select records to import
    - Apply imports manually
    
    🔵 **Blue background** = Values from JSON files (not yet in MongoDB)
    ✅ **Validated** = Document type matches target collection
    rv   r  )r1   re   re   re   u   ✅ Import Selected Recordsrg   r   )ri   r   u   ❌ Mark All Skipmark_all_skip)r4   r*  reset_decisionsr   c                 <    g | ]}|                     d           |S r   ry   r   s     r(   r=   z+_render_new_records_tab.<locals>.<listcomp>  s)    CCC!c1B1BCACCCr*   r   r   zS data fields (all nested fields flattened). Scroll horizontally to see all columns.zImport?)pendingimportr6  Tz$Select whether to import this recordr1  r7  Rowz	Row index)r2  r5   r   )_import_decision
_row_indexrD   )int64int32float64float32zNumeric value from JSON filer   boolzBoolean value from JSON filezValue from JSON filer0  i  new_records_editor_r=  z### Import SummaryrF   z	To Importrm  zTo Skipr6  Pendingrl  u   ⚠️ Ready to import z
 record(s)pending_importre   u   🚀 Apply Importsapply_imports_btnrh   r   )r   import_indicesrg  rM  )r   rS   r   r   r   r   rN   r   r   r   rv   r   rK   rj   mark_all_for_importr   rC  r?  rH  rF  rz   dtypeCheckboxColumnrG  rE  r.   extract_import_decisionsrU   rx  _show_import_confirmation)r   r'   r"   rg  r   validated_recordsr   rW   rX   rb   r   data_columnsr?  r  r|  rL  	decisionss                    r(   r   r     s    -(K 
-... _jxA}599:NPYZZZox hh{hhhhhJms;''mmYjmmmnnnC,,, d
V,VVVWWWW

b"3bbc+6F6FbbbcccK  	 	 	  r'77 
2@2X2X3
 3
/
 
		0B	x   Z55D$d	  92)TTT 	6D6X6XY[6\6\B3HJJJ              
 
  9(o>>> 	6D6V6VWY6Z6ZB3HJJJ              
 
  9\'8999 	6D6\6\7 7B3 HJJJ               K DCrzCCCLG  ]s2ww  ]  ]c,6G6G  ]  ]  ]  ^  ^  ^ ,<<1117 = 
 
 &33	 4 
 
 M" z  ~~c"" 	sGME@@ %'%5%B%B8 &C & &c"" & 
%'%5%D%D8 &E & &c"" &(%5%@%@0 &A & &c" 
#D""2"BDD  I /8B+ 77	BBI K$%%%z!}}D$	 9 9
	+s9X#6778889 9 9 9 9 9 9 9 9 9 9 9 9 9 9 
 5 5
	)S6!2334445 5 5 5 5 5 5 5 5 5 5 5 5 5 5 
 8 8
	)S9!5667778 8 8 8 8 8 8 8 8 8 8 8 8 8 8 9X!#  
E

QS81D-E-EQQQRRR 2#33 	3.2B+ZA''
d 	 	y$'    (//@'A&/&9#."+	3 3 / 


	 	 	 	 	 	 	 	 	 	 	 	 	 	 	  * 	% /    9   6	 	s   AF55F9<F9AHH #H )AJJJ)RRR)SSS)TTT/AXXXc                    | d         }|st          j        d           dS t          j        dt          |           d           t          j        d           |D ]}t          j        d|            t          j        d           dS )	zRender new fields tab.r.  u   ℹ️ No new fields detectedNrA   z new field(s) found in JSONz
    These fields exist in JSON but not in MongoDB.
    
    **Recommendation:** Use the Schema Manager to add these fields before importing.
    u   • uH   💡 Go to the collection tab and use Schema Manager to add these fields)r   rS   rN   r   r   r   )r   r.  r   s      r(   r   r     s    &J 
/000JCs:CCCDDDK  	 	 	     
uGVWWWWWr*   pending_datac                 r   | d         }| d         }| d         }| d         }t          j        d           t          j        dt          |           d| d           t          j        d	          \  }}|5  t          j        d
ddd          r&g }	|D ]L}
t          |
t                    r d|
v r|	                    |
d                    7|	                    |
           M|	r|	d         	                    d|          n|}|
                    ||	|d          }t          |          dk    r"t          j        d           	 ddd           dS |                    |          }|&t          j        d| d           	 ddd           dS 	 t          j        dt          |           d| d          5  |                    |          }ddd           n# 1 swxY w Y   t          j        dt          |j                   d| d           dt           j        _        dt           j        _        dt           j        _        dt           j        _        t          j        d           t          j                     n;# t.          $ r.}t          j        d t1          |                      Y d}~nd}~ww xY wddd           n# 1 swxY w Y   |5  t          j        d!d"d#          r8dt           j        _        t          j        d$           t          j                     ddd           dS # 1 swxY w Y   dS )%a  
    Show import confirmation dialog and execute import.
    
    Args:
        pending_data: Dictionary with collection_name, import_indices, new_records, preview_df
        preview_engine: ImportPreviewEngine instance
        mongo_service: MongoService instance
    r   rz  rg  rM  u   ### ⚠️ Confirm Importz
    **You are about to import z record(s) to `zp`**
    
    This action will:
    - Insert new documents into MongoDB
    - Cannot be undone automatically
    r1   u   ✅ Confirm Importconfirm_import_btnrg   r   rP  r  r   rn   T)	unflattenu#   ❌ No records prepared for import!Nu   ❌ Collection `z%` not found or MongoDB not connected!z
Importing z records to z...u   ✅ Successfully imported z records to collection: `rC   FrU  u   ❌ Failed to import: rV  cancel_import_btnrX  zImport cancelled)r   r   r   r   rK   rj   
isinstancedictrQ   r   prepare_records_for_importrZ  r   insert_manyr   inserted_idsr   rv   r   r,   rx  rS   balloonsr]  r^  r   )r  r'   r"   r   rz  original_recordsrM  rW   rX   r   recr   records_to_importr`  rd  re  s                   r(   r  r    s    ##45O!"23N#M2l+JK+,,,H ">22 CR   	 	 	 AJD$	 6< 6<9 $	
 
 
 5	< L' - -c4(( -]c-A - ''M(:;;;; '',,,, _k Q 3 34H/ Z Z Zp !/ I I	 !J ! ! $%%* >???;6< 6< 6< 6< 6< 6< 6< 6<@ '556GHHJ d,=dddeeeI6< 6< 6< 6< 6< 6< 6< 6<L<Z gS1B-C-C g gQb g g ghh G G'334EFFFG G G G G G G G G G G G G G G 
F<O8P8Pk|  A  A  A ;? 76: 35: 226 /KLLL < < <:#a&&::;;;;;;;;<k6< 6< 6< 6< 6< 6< 6< 6< 6< 6< 6< 6< 6< 6< 6<p 
  9#
 
 
 	
 /3B+G&'''HJJJ                 s{   6CK0K(I;5GI;G	I;G	BI;:K;
J3$J.)K.J33KK	KAL,,L03L0)N)$__doc__	streamlitr   pandaspdtypingr   r   r   services.json_loaderr   services.diff_enginer   services.import_preview_enginer   services.update_enginer	   services.data_servicer
   bsonr   r^  r)   r   r   r    rk   r!   r   r   r   	DataFramerI  r   r   r  r/   r*   r(   <module>r     sY            " " " " " " " " " " + + + + + + + + + + + + > > > > > > / / / / / / - - - - - -       	== ==== cN==
 
== == == ==@- - -*^;
 ^;DQTVYQYN ^; ^; ^; ^;L $ $$ $ 	$ $ $ $X Z ZZ Z 	Z Z Z ZzC(*= C( C( C( C(L'
tCH~ '
GZ '
 '
 '
 '
T
#s(^
'
 
 
 
DdT#s(^$dd d d dNggg T#s(^$g  	g g g gTp#s(^p'p p p pfXDcN X X X X.^sCx.^'^ ^ ^ ^ ^ ^r*   