
    ג[i+                     \    d Z ddlmZmZmZmZ ddlZddlmZ ddl	m
Z
  G d d          ZdS )a5  
Import Preview Engine

This module builds editable preview tables for import decisions.
It tracks user decisions per row (import/skip) without performing any writes.

Key principles:
- NO database writes
- User decisions tracked in memory
- Field-level editing supported
- All changes reversible until apply
    )ListDictAnyOptionalN)datetime)JSONFlattenerc                      e Zd ZdZd Z	 ddeeeef                  dede	j
        fdZdeeeef                  de	j
        fd	Zd
e	j
        deeee         f         fdZ	 dd
e	j
        deeeef                  dee         dedeeeef                  f
dZdeeee         f         dedeeef         fdZd
e	j
        de	j
        fdZd
e	j
        de	j
        fdZd
e	j
        deeef         fdZdS )ImportPreviewEnginez
    Service for building and managing import preview data.
    
    Allows users to review, edit, and make decisions about records
    before importing them to MongoDB.
    c                 ,    t                      | _        dS )z!Initialize import preview engine.N)r   	flattener)selfs    :/var/www/html/IGF-ODF-V3/services/import_preview_engine.py__init__zImportPreviewEngine.__init__   s    &    newrecordsrecord_typereturnc                    |st          j                    S g }t          |          D ][\  }}|dk    r*|                    di                                           }n|dk    r|                    di           }|                    di           }|                    di           }	|                                }|                    dd          |d<   |                    d	d
          |d<   |	                    dd          |d<   n^|dk    rV|                    di                                           }|                    di                               d	d
          |d<   ni }||d<   d|d<   |                    |           ]t          j        |          }
|
                    t          j        |
          d          }
|
S )a  
        Build a DataFrame for preview and editing.
        
        Args:
            records: List of records to preview
            record_type: Type of records ('new', 'duplicate', 'exact')
            
        Returns:
            DataFrame with preview data
        r   json_record	duplicate	db_record
comparison
match_typeunknown_match_type_id _db_iddifference_countr   _difference_countexact
_row_indexpending_import_decisionN)pd	DataFrame	enumerategetcopyappendwherenotnull)r   r   r   preview_datairecordrow_datajson_recdb_recr   dfs              r   build_preview_dataframez+ImportPreviewEngine.build_preview_dataframe    s     	"<>>! "7++ 	* 	*IAve# !::mR88==??+ !::mR88K44#ZZb99
 $==?? +1**\9*M*M'%+ZZr%:%:"0:?QST0U0U,--' !::mR88==??%+ZZR%@%@%D%DUB%O%O"" &'H\" ,5H'()))) \,'' XXbjnnd++	r   
duplicatesc                    |st          j                    S g }t          |          D ]e\  }}|                    di           }|                    di           }|                    di           }|                    di           }t	          |                                          t	          |                                          z  }	|	D ]}
|
dk    r	|                    |
          }|                    |
          }|
|v r||
         d         }nd}|t          |          nd}|t          |          nd}|                    ||                    d	d
          t          |                    dd                    |
|||dd           gt          j        |          }|                    t          j	        |          d          }|S )z
        Build a side-by-side comparison DataFrame for duplicates.
        
        Args:
            duplicates: List of duplicate records with comparison data
            
        Returns:
            DataFrame with JSON vs DB comparison
        r   r   r   differencesr   statusmatchNr   r   r   r$   )r#   r   r   field
json_valuedb_valuer9   r%   )
r&   r'   r(   r)   setkeysstrr+   r,   r-   )r   r6   comparison_datar/   dupr2   r3   r   r8   
all_fieldsr;   r<   r=   r9   json_value_strdb_value_strr4   s                    r   $build_duplicate_comparison_dataframez8ImportPreviewEngine.build_duplicate_comparison_dataframe]   s     	"<>>!
++ #	 #	FAsww}b11HWW["--Fr22J$..;;K X]]__--FKKMM0B0BBJ#  E> %\\%00
!::e,, K' %(/9FF$F 5?!TZPT08Ns8}}}$&&"##&77<#C#C!&**UB"7"788""0 ,$(1	( 	( 	 	 	 	#8 \/**XXbjnnd++	r   
preview_dfc                 t   |j         s	d|j        vrg g g dS g g g d}|                                D ]\  }}|                    dd          }|                    d|          }||v r)||                             t          |                     ^|d                             t          |                     |S )z
        Extract user import decisions from preview DataFrame.
        
        Args:
            preview_df: DataFrame with user decisions
            
        Returns:
            Dictionary with lists of row indices by decision
        r%   )importskipr$   r$   r#   )emptycolumnsiterrowsr)   r+   int)r   rG   	decisionsidxrowdecision	row_indexs          r   extract_import_decisionsz,ImportPreviewEngine.extract_import_decisions   s      	19KK 	   
 
	 #++-- 	< 	<HCww19==Hc22I9$ <(#**3y>>::::)$++C	NN;;;;r   Foriginal_recordsimport_indices	unflattenc                    g }|D ]}|t          |          k    r|j        |         }|                                }g d}	|	D ]}
|                    |
d           d |                                D             }d |                                D             }|r| j                            |          }|                    |           |S )a  
        Prepare records for import based on user decisions and edits.
        
        Args:
            preview_df: DataFrame with user edits (flattened columns)
            original_records: Original record list
            import_indices: List of row indices to import
            unflatten: If True, convert flattened records back to nested structure
            
        Returns:
            List of records ready for import (flattened or nested)
        )r#   r%   r   r   r!   _source_file_source_path_source_competition_target_collection_validation_passed_document_type_expected_typesNc                 D    i | ]\  }}|                     d           ||S )_)
startswith.0kvs      r   
<dictcomp>zBImportPreviewEngine.prepare_records_for_import.<locals>.<dictcomp>   s/    OOOtq!Q\\#=N=NOaOOOr   c                 B    i | ]\  }}t          j        |          ||S  )r&   notnarc   s      r   rg   zBImportPreviewEngine.prepare_records_for_import.<locals>.<dictcomp>   s+    EEEtq!!EaEEEr   )lenilocto_dictpopitemsr   rW   r+   )r   rG   rU   rV   rW   records_to_importrP   rQ   r0   metadata_fieldsr;   s              r   prepare_records_for_importz.ImportPreviewEngine.prepare_records_for_import   s    & ! '	- '	-Cc*oo%  /#&C [[]]F  O ) ( (

5$'''' POv||~~OOOF FEv||~~EEEF  :11&99$$V,,,,  r   rO   c           
      ,   |t          d |                                D                       t          |                    dg                     t          |                    dg                     t          |                    dg                     |dS )z
        Build a summary of import decisions.
        
        Args:
            decisions: Dictionary with decision lists
            record_type: Type of records
            
        Returns:
            Summary dictionary
        c              3   4   K   | ]}t          |          V  d S )N)rk   )rd   rf   s     r   	<genexpr>z;ImportPreviewEngine.build_import_summary.<locals>.<genexpr>  s(       D DAQ D D D D D Dr   rI   rJ   r$   )r   total_records	to_importto_skipr$   rO   )sumvaluesrk   r)   )r   rO   r   s      r   build_import_summaryz(ImportPreviewEngine.build_import_summary   s      '  D D1A1A1C1C D D DDDY]]8R88999==44559==B7788"
 
 	
r   c                 "    d|j         v rd|d<   |S )z
        Mark all records in preview for import.
        
        Args:
            preview_df: Preview DataFrame
            
        Returns:
            Updated DataFrame
        r%   rI   rL   r   rG   s     r   mark_all_for_importz'ImportPreviewEngine.mark_all_for_import  s%     !33 	6-5J)*r   c                 "    d|j         v rd|d<   |S )z
        Mark all records in preview to skip.
        
        Args:
            preview_df: Preview DataFrame
            
        Returns:
            Updated DataFrame
        r%   rJ   r}   r~   s     r   mark_all_for_skipz%ImportPreviewEngine.mark_all_for_skip(  s%     !33 	4-3J)*r   c           	         |j         ri S g dfd|j        D             }i }|D ]}||                                                                         }||                                                                         }t          |          t          |          t          |          dk    r#t          |t          |          z  dz  d          ndd||<   |S )z
        Get statistics about fields in preview data.
        
        Args:
            preview_df: Preview DataFrame
            
        Returns:
            Dictionary with field statistics
        )r#   r%   r   r   r!   c                     g | ]}|v|	S ri   ri   )rd   colrq   s     r   
<listcomp>z<ImportPreviewEngine.get_field_statistics.<locals>.<listcomp>S  s#    WWWsC<VWsWWWr   r   d      )non_null_count
null_countcoverage_percentage)rK   rL   rj   ry   isnarN   rk   round)r   rG   data_fieldsfield_statsr;   r   r   rq   s          @r   get_field_statisticsz(ImportPreviewEngine.get_field_statistics:  s     	I
 
 
 XWWWj&8WWW  	 	E'.4466::<<N#E*//115577J #&n"5"5!*oo]`ak]l]lop]p'wuns:.NQT.TWX'Y'Y'Yvw" "K r   N)r   )F)__name__
__module____qualname____doc__r   r   r   r@   r   r&   r'   r5   rF   rN   rT   boolrr   r{   r   r   r   ri   r   r   r
   r
      s        ) ) ) !; ;d38n%; ; 
	; ; ; ;z:c3h(: 
: : : :x#L# 
c49n	# # # #T  >! >!L>! tCH~.>! S		>!
 >! 
d38n	>! >! >! >!@
T#Y'
 
 
c3h	
 
 
 
0L 
   $L 
   $'L' 
c3h' ' ' ' ' 'r   r
   )r   typingr   r   r   r   pandasr&   r   services.json_flattenerr   r
   ri   r   r   <module>r      s     - , , , , , , , , , , ,           1 1 1 1 1 1M M M M M M M M M Mr   