"""
FFEv3.0 Feature Engineering Console

Based on FFEv2.0, with significant optimizations
Integrates preprocessing tools for comprehensive feature engineering

Main features:
1. Intelligent scheduling of preprocessing tools
2. Batch processing for large datasets
3. Detailed preprocessing execution
4. Real-time quality assessment
5. Comprehensive processing reports
6. Data visualization support
7. Logging system integration
8. Easy-to-use API
"""

import sys
import os
import pandas as pd
import time
import json
from datetime import datetime

# Add MFM project root to Python path
sys.path.append(os.path.abspath('.'))

from myffe.tools.color_printer import ColorPrinter
from myffe.core.master_judge import evaluate_dataset, print_evaluation_result
from myffe.tools.save_params import save_config, process_save_path

# Preprocessing tools order - from basic to advanced
clean_ways = [
    "nan_preprocessing",      # 1. Missing value handling
    "autoencoder_preprocessing", # 2. Autoencoder imputation
    "outlier_preprocessing",  # 3. Outlier detection
    "str_preprocessing",      # 4. Text feature processing
    "time_preprocessing",     # 5. Time feature processing
    "relative_preprocessing", # 6. Relative feature processing
    "specify_preprocessing",  # 7. Custom feature processing
    "sample_preprocessing",   # 8. Data sampling
    "standard_preprocessing", # 9. Standardization
    "normalized_preprocessing", # 10. Normalization
]


class FFE_console:
    """
    FFEv3.0 Feature Engineering Console
    """
    
    def __init__(self, data_label, ways='auto', batch_size=None, enable_logging=True, enable_visualization=True, enable_quality_assessment=True, use_modin=False, save_params=None):
        """
        Initialize FFE console

        Args:
            data_label (str): Label column name
            ways (str): Processing method
                - 'auto': Automatic tool ordering
                - 'intelligent': Intelligent tool ordering based on data analysis
                - 'pass': Use tools in provided order
            batch_size (int): Batch size for large data processing, None for no batching
            enable_logging (bool): Whether to enable logging, default True
            enable_visualization (bool): Whether to enable visualization, default True
            enable_quality_assessment (bool): Whether to enable quality assessment, default True
            use_modin (bool): Whether to use Modin for data processing, default False
            save_params (str): Path to save parameters after processing, None for no saving
        """
        self.data_label = data_label
        self.ways = ways
        self.batch_size = batch_size
        self.enable_logging = enable_logging
        self.enable_visualization = enable_visualization
        self.enable_quality_assessment = enable_quality_assessment
        self.use_modin = use_modin
        self.save_params = save_params
        self.data = None
        self.text_features = None
        self.str_confirm = False
        self.performance_stats = {}
        self.quality_metrics = {}
        self.processing_history = []
        
        ColorPrinter.print_info("FFEv3.0 Feature Engineering Console")
        ColorPrinter.print_info(f"Label: {data_label}")
        ColorPrinter.print_info(f"Processing way: {ways}")
        if batch_size:
            ColorPrinter.print_info(f"Batch size: {batch_size}")
        ColorPrinter.print_info(f"Logging: {'Enabled' if enable_logging else 'Disabled'}")
        ColorPrinter.print_info(f"Visualization: {'Enabled' if enable_visualization else 'Disabled'}")
        ColorPrinter.print_info(f"Quality assessment: {'Enabled' if enable_quality_assessment else 'Disabled'}")
        if save_params:
            ColorPrinter.print_info(f"Save params to: {save_params}")
        else:
            ColorPrinter.print_info("Save params: Disabled")
        ColorPrinter.print_any("")
    
    def __call__(self, clean_tools, data, save_path='./clean_data/data00.csv', describe_data=True):
        """
        Execute feature engineering with preprocessing tools

        Args:
            clean_tools (dict): Preprocessing tools dictionary
            data (DataFrame): Input data
            save_path (str): Path to save processed data
            describe_data (bool): Whether to describe data before and after processing, default True

        Returns:
            DataFrame: Processed data
        """
        start_time = time.time()
        
        
#region  Check if Modin should be used
        if self.use_modin:
            try:
                import modin.pandas as pd
                # Convert pandas DataFrame to Modin DataFrame if needed
                if not hasattr(data, '_query_compiler'):
                    data = pd.DataFrame(data)
                ColorPrinter.print_info("Using Modin for data processing")
            except ImportError:
                ColorPrinter.print_warning("Modin not installed, falling back to pandas")
                import pandas as pd
        else:
            import pandas as pd
#endregion
        
#region 初始化参数
        self.clean_ways_dict = clean_tools
        self.data = data.copy()
        self.save_path = save_path
#endregion   
        
        
        
#region  Configure logging
        try:
            from myffe.tools.Loggerv1_1 import set_logging_enabled
            set_logging_enabled(self.enable_logging)
            # Logging configuration based on enable_logging parameter
        except ImportError:
            ColorPrinter.print_warning("Warning: Failed to configure logging system")
#endregion

#region Processed data description

        if describe_data:
            # Separate label column if it exists for description
            if self.data_label in self.data.columns:
                label_data = self.data[[self.data_label]].copy()
                feature_data = self.data.drop(columns=[self.data_label])
            else:
                label_data = None
                feature_data = self.data.copy()
            self._describe_data(feature_data, label_data, "Original Data Description")
#endregion
        
#region Initial data quality assessment
        if self.enable_quality_assessment:
            self._assess_data_quality(self.data, "initial")
#endregion
        
#region Tool ordering
        self.sorting(self.clean_ways_dict)
#endregion
        
#region Execute preprocessing
        self.clean_console()
#endregion
        
#region Merge text features if available
        if self.str_confirm and self.text_features is not None:
            self.data = pd.concat([self.data, self.text_features], axis=1)
            ColorPrinter.print_success("OK Text features merged successfully")
#endregion
        
#region Final data quality assessment
        if self.enable_quality_assessment:
            self._assess_data_quality(self.data, "final")
#endregion
        
#region Save processed data
        self.save_data()
#endregion
        
#region Processed data description
        if describe_data:
            # Separate label column if it exists for description
            if self.data_label in self.data.columns:
                label_data = self.data[[self.data_label]].copy()
                feature_data = self.data.drop(columns=[self.data_label])
            else:
                label_data = None
                feature_data = self.data.copy()
            self._describe_data(feature_data, label_data, "Processed Data Description")
        
        # Generate processing report
        self._generate_processing_report(start_time)
#endregion    
        
        # Save parameters if path is provided
        if self.save_params:
            self._save_parameters()
        
        return self.data

    def sorting(self, clean_tools):
        """
        Sort preprocessing tools based on selected method
        
        Args:
            clean_tools (dict): Preprocessing tools dictionary
        """
        if self.ways == 'auto':
            sorted_dict = {}
            for tool_name in clean_ways:
                if tool_name in clean_tools:
                    sorted_dict[tool_name] = clean_tools[tool_name]
            self.clean_ways_dict = sorted_dict
        elif self.ways == 'intelligent':
            # Intelligent tool ordering based on data analysis
            sorted_dict = self._intelligent_sorting(clean_tools)
            self.clean_ways_dict = sorted_dict
        elif self.ways == 'pass':
            self.clean_ways_dict = clean_tools
        else:
            ColorPrinter.print_error(f"Invalid processing way: {self.ways}, using pass mode")
            self.clean_ways_dict = clean_tools
    
    def clean_console(self):
        """
        Execute preprocessing tools on data
        """
        try:
            if self.batch_size is not None and len(self.data) > self.batch_size:
                self.data = self._process_in_batches()
            else:
                self.data = self._process_single_batch(self.data)
        except Exception as e:
            ColorPrinter.print_error(f"Processing error: {e}")
            raise

    def _describe_data(self, data, label_data, title):
        """
        Describe data by combining with label if available
        
        Args:
            data (DataFrame): Feature data
            label_data (DataFrame): Label data
            title (str): Description title
        """
        ColorPrinter.print_any("\n" + "=" * 80)
        ColorPrinter.print_info(title)
        ColorPrinter.print_any("=" * 80)
        try:
            from myffe.tools.data_description import describe_data
            # Combine with label for description if available
            if label_data is not None:
                describe_data(pd.concat([data, label_data], axis=1))
            else:
                describe_data(data)
        except ImportError:
            ColorPrinter.print_warning("Warning: Failed to load data description module")
        ColorPrinter.print_any("=" * 80 + "\n")
    
#这个是单个清理工具的使用，启动的必经之路
    def _process_single_batch(self, batch_data):
        """
        Process a single batch of data
        
        Args:
            batch_data (Batch_data): Batch of data to process
            
        Returns:
            DataFrame: Processed data
        """
        processed_data = batch_data.copy()

        for tool_name in self.clean_ways_dict.keys():
            ColorPrinter.print_info(f"Processing: {tool_name}")


#region start time
            start_tool_time = time.time()
#endregion

#region Pre-quality assessment   
            if self.enable_quality_assessment:
                pre_quality = self._calculate_quality_metrics(processed_data)
#endregion     
            
#region preprocessing
            try:
                processed_data = self._execute_preprocessing(tool_name, processed_data)
            except Exception as e:
                ColorPrinter.print_error(f"Error processing {tool_name}: {str(e)}")
                # Keep original data if error occurs
                ColorPrinter.print_info(f"Keeping original data for {tool_name}")
# endregion

#region  Post-quality assessment and count time
            if self.enable_quality_assessment:
                post_quality = self._calculate_quality_metrics(processed_data)
                quality_change = {k: post_quality.get(k, 0) - pre_quality.get(k, 0) for k in set(pre_quality.keys())}
                self.processing_history.append({
                    'tool': tool_name,
                    'execution_time': time.time() - start_tool_time,
                    'quality_change': quality_change
                })
            else:
                self.processing_history.append({
                    'tool': tool_name,
                    'execution_time': time.time() - start_tool_time
                })
#endregion    

#region  Processed data description and count time
            self._describe_data(processed_data, None, f"After {tool_name} Processing")
            ColorPrinter.print_success(f"OK {tool_name} completed (Time: {time.time() - start_tool_time:.2f} s)")
#endregion
        
        # 返回处理后的完整数据
        return processed_data
    
    def _process_in_batches(self):
        """
        Process data in batches

        Returns:
            DataFrame: Processed data
        """
#region input the info 
        ColorPrinter.print_warning(f"Processing in batches: {self.batch_size}")
        ColorPrinter.print_info(f"Total rows: {len(self.data)}")
        ColorPrinter.print_info(f"Number of batches: {(len(self.data) + self.batch_size - 1) // self.batch_size}")
        ColorPrinter.print_any("")

#region Create batch data list
        batches = []
        batch_count = 0

        for i in range(0, len(self.data), self.batch_size):
            batch_count += 1
            batch_data = self.data.iloc[i:i + self.batch_size].copy()
            batches.append((batch_count, batch_data, i+1, min(i+self.batch_size, len(self.data))))
#endregion
        
#region Use multiprocessing for parallel processing 
        try:
            import multiprocessing
            from multiprocessing import Pool

            # Determine number of processes to use
            num_processes = min(multiprocessing.cpu_count(), len(batches))
            ColorPrinter.print_info(f"Using {num_processes} processes for parallel processing")

            # Process batches in parallel
            with Pool(processes=num_processes) as pool:
                results = pool.starmap(self._process_batch_wrapper, batches)

            # Collect results
            batch_data_list = []
            for batch_count, processed_batch in results:
                batch_data_list.append(processed_batch)
                ColorPrinter.print_success(f"OK Batch {batch_count} completed")

        except ImportError:
            # Fallback to sequential processing if multiprocessing is not available
            ColorPrinter.print_warning("Multiprocessing not available, falling back to sequential processing")
            batch_data_list = []
            for batch_count, batch_data, start_row, end_row in batches:
                ColorPrinter.print_warning(f"Batch {batch_count}: Rows {start_row}-{end_row}")
                processed_batch = self._process_single_batch(batch_data)
                batch_data_list.append(processed_batch)
                ColorPrinter.print_success(f"OK Batch {batch_count} completed")
                ColorPrinter.print_any("")
#endregion


        processed_data = pd.concat(batch_data_list, ignore_index=True)
        ColorPrinter.print_success(f"All {len(batches)} batches processed successfully")
        return processed_data

    def _process_batch_wrapper(self, batch_count, batch_data, start_row, end_row):
        """
        Wrapper function for batch processing in multiprocessing

        Args:
            batch_count (int): Batch number
            batch_data (DataFrame): Batch data
            start_row (int): Start row index
            end_row (int): End row index

        Returns:
            tuple: (batch_count, processed_batch)
        """
        import sys
        import os
        # Add the project root to Python path for each process
        sys.path.append(os.path.abspath('.'))

        # Process the batch
        processed_batch = self._process_single_batch(batch_data)
        return (batch_count, processed_batch)
    



    def _execute_preprocessing(self, tool_name, data):
        """
        Execute preprocessing tool
        
        Args:
            tool_name (str): Preprocessing tool name
            data (DataFrame): Input data (包含完整数据集，包括标签列)
            
        Returns:
            DataFrame: Processed data
        """
#region 获取工具并且检查是否存在
        processor = self.clean_ways_dict.get(tool_name)
        if processor is None:
            ColorPrinter.print_error(f"Error: Preprocessing tool {tool_name} not found")
            return data
#endregion
#region  Handle NaN values for standardization and normalization
        if tool_name in ['standard_preprocessing', 'normalized_preprocessing']:
            numeric_cols = data.select_dtypes(include=['number']).columns
            if numeric_cols.size > 0:
                # Check for NaN values
                has_nan = data[numeric_cols].isnull().any().any()
                if has_nan:
                    ColorPrinter.print_warning(f"Warning: {tool_name} requires no NaN values, filling with mean")
                    # Fill NaN values
                    for col in numeric_cols:
                        if data[col].isnull().any().any():
                            data[col] = data[col].fillna(data[col].mean())
                            ColorPrinter.print_info(f"  Filled NaN values in {col}")
#endregion
#region Execute preprocessing based on tool type
        if tool_name == 'nan_preprocessing':
            return processor(data)
        
        elif tool_name == 'sample_preprocessing':
            return processor(data, data_label=self.data_label)
        
        elif tool_name == 'outlier_preprocessing':
            return processor(data, self.data_label)
        
        elif tool_name == 'str_preprocessing':
            result = processor(data, self.data_label)
            # Handle text features
            if isinstance(result, tuple):
                processed_data, text_features = result
                if not self.str_confirm:
                    self.text_features = text_features
                self.str_confirm = True
            else:
                processed_data = result
            return processed_data
        
        elif tool_name == 'relative_preprocessing':
            params = processor.shortcut_relative
            relative_type = params.get('relative_type', 'normal')
            return processor(data, relative_type, self.data_label)
        
        elif tool_name == 'time_preprocessing':
            return processor(data)
        
        elif tool_name == 'specify_preprocessing':
            return processor(data)
        
        elif tool_name == 'standard_preprocessing':
            try:
                processed_data = processor(data)
                return processed_data
            except Exception as e:
                ColorPrinter.print_error(f"Error in standard_preprocessing: {str(e)}")
                return data
        
        elif tool_name == 'normalized_preprocessing':
            try:
                processed_data = processor(data)
                return processed_data
            except Exception as e:
                ColorPrinter.print_error(f"Error in normalized_preprocessing: {str(e)}")
                return data
        
        elif tool_name == 'autoencoder_preprocessing':
            try:
                processed_data = processor(data, self.data_label)
                return processed_data
            except Exception as e:
                ColorPrinter.print_error(f"Error in autoencoder_preprocessing: {str(e)}")
                return data
        
        else:
            ColorPrinter.print_error(f"Error: Unknown preprocessing tool {tool_name}")
            return data
#endregion
    def save_data(self):
        """
        Save processed data to file
        """
        if self.save_path:
            save_dir = os.path.dirname(self.save_path)
            if save_dir and not os.path.exists(save_dir):
                os.makedirs(save_dir)
            
            self.data.to_csv(self.save_path, index=False)
            ColorPrinter.print_success(f"\nData saved to: {self.save_path}")
            ColorPrinter.print_info(f"Shape: {self.data.shape}")
            ColorPrinter.print_info(f"Columns: {len(self.data.columns)}")
    
    def _intelligent_sorting(self, clean_tools):
        """
        Intelligently sort preprocessing tools based on data analysis
        
        Args:
            clean_tools (dict): Preprocessing tools dictionary
            
        Returns:
            dict: Sorted preprocessing tools
        """
        # Analyze data
        data_analysis = {
            'has_nan': self.data.isnull().any().any(),
            'has_outliers': False,  # Placeholder for outlier detection
            'has_text': any(self.data.dtypes == 'object'),
            'has_time': False,  # Placeholder for time feature detection
            'needs_sampling': len(self.data) > 10000,  # Simple heuristic for sampling
        }
        
        # Intelligent tool order
        intelligent_order = []
        
        # 1. Handle missing values first
        if data_analysis['has_nan'] and 'nan_preprocessing' in clean_tools:
            intelligent_order.append('nan_preprocessing')
        
        # 2. Handle outliers
        if data_analysis['has_outliers'] and 'outlier_preprocessing' in clean_tools:
            intelligent_order.append('outlier_preprocessing')
        
        # 3. Process text features
        if data_analysis['has_text'] and 'str_preprocessing' in clean_tools:
            intelligent_order.append('str_preprocessing')
        
        # 4. Process time features
        if data_analysis['has_time'] and 'time_preprocessing' in clean_tools:
            intelligent_order.append('time_preprocessing')
        
        # 5. Relative feature processing
        if 'relative_preprocessing' in clean_tools:
            intelligent_order.append('relative_preprocessing')
        
        # 6. Custom feature processing
        if 'specify_preprocessing' in clean_tools:
            intelligent_order.append('specify_preprocessing')
        
        # 7. Data sampling (if needed)
        if data_analysis['needs_sampling'] and 'sample_preprocessing' in clean_tools:
            intelligent_order.append('sample_preprocessing')
        
        # 8. Normalization and standardization
        if 'standard_preprocessing' in clean_tools:
            intelligent_order.append('standard_preprocessing')
        if 'normalized_preprocessing' in clean_tools:
            intelligent_order.append('normalized_preprocessing')
        
        # Create sorted dictionary
        sorted_dict = {}
        for tool_name in intelligent_order:
            if tool_name in clean_tools:
                sorted_dict[tool_name] = clean_tools[tool_name]
        
        # Add remaining tools
        for tool_name in clean_tools:
            if tool_name not in sorted_dict:
                sorted_dict[tool_name] = clean_tools[tool_name]
        
        ColorPrinter.print_warning(f"Intelligent order: {list(sorted_dict.keys())}")
        return sorted_dict
    
    def _assess_data_quality(self, data, stage):
        """
        Assess data quality
        
        Args:
            data (DataFrame): Data to assess
            stage (str): Stage of processing (initial, final)
        """
        # 使用新的评价系统
        evaluation_result = evaluate_dataset(data, label_column=self.data_label)
        
        # 保持向后兼容的质量指标
        metrics = self._calculate_quality_metrics(data)
        self.quality_metrics[stage] = metrics
        
        if self.enable_visualization:
            ColorPrinter.print_info(f"\n{stage} Data Quality Metrics:")
            # 打印新的评价结果
            print_evaluation_result(evaluation_result)
            # 保持原有的指标输出以保持兼容性
            ColorPrinter.print_info("\nTraditional Quality Metrics:")
            for key, value in metrics.items():
                ColorPrinter.print_info(f"  - {key}: {value:.4f}")
    
    def _calculate_quality_metrics(self, data):
        """
        Calculate data quality metrics
        
        Args:
            data (DataFrame): Data to analyze
            
        Returns:
            dict: Quality metrics
        """
        metrics = {}
        
        # Missing value ratio
        total_cells = data.size
        missing_cells = data.isnull().sum().sum()
        metrics['missing_value_ratio'] = missing_cells / total_cells if total_cells > 0 else 0
        
        # Data type diversity
        unique_dtypes = len(data.dtypes.unique())
        metrics['dtype_diversity'] = unique_dtypes / len(data.columns) if len(data.columns) > 0 else 0
        
        # Mean variance of numeric features
        numeric_cols = data.select_dtypes(include=['number']).columns
        if len(numeric_cols) > 0:
            variances = data[numeric_cols].var()
            metrics['mean_variance'] = variances.mean() if len(variances) > 0 else 0
        else:
            metrics['mean_variance'] = 0
        
        # Feature count
        metrics['feature_count'] = len(data.columns)
        
        return metrics
    
    def _save_parameters(self):
        """
        Save parameters from all preprocessing tools
        """
        import os
        from datetime import datetime
        
        # Extract parameters from all tools
        params_dict = {
            'label_column': self.data_label,
            'processing_way': self.ways,
            'batch_size': self.batch_size,
            'enable_logging': self.enable_logging,
            'enable_visualization': self.enable_visualization,
            'enable_quality_assessment': self.enable_quality_assessment,
            'use_modin': self.use_modin,
            'timestamp': datetime.now().isoformat(),
            'tools': {}
        }
        
        # Extract parameters from each tool
        for tool_name, tool_instance in self.clean_ways_dict.items():
            tool_params = {}
            
            # Try to get shortcut parameters
            if hasattr(tool_instance, 'shortcut_nan'):
                tool_params['nan_ways'] = tool_instance.shortcut_nan
            elif hasattr(tool_instance, 'shortcut_outlier'):
                tool_params['outlier_params'] = tool_instance.shortcut_outlier
            elif hasattr(tool_instance, 'shortcut_str'):
                tool_params['str_params'] = tool_instance.shortcut_str
            elif hasattr(tool_instance, 'shortcut_time'):
                tool_params['time_params'] = tool_instance.shortcut_time
            elif hasattr(tool_instance, 'shortcut_relative'):
                tool_params['relative_params'] = tool_instance.shortcut_relative
            elif hasattr(tool_instance, 'shortcut_specify'):
                tool_params['specify_params'] = tool_instance.shortcut_specify
            elif hasattr(tool_instance, 'shortcut_sample'):
                tool_params['sample_params'] = tool_instance.shortcut_sample
            elif hasattr(tool_instance, 'shortcut_norm'):
                tool_params['norm_params'] = tool_instance.shortcut_norm
            
            # Add any other relevant attributes
            for attr in dir(tool_instance):
                if not attr.startswith('_') and not callable(getattr(tool_instance, attr)):
                    if attr not in tool_params:
                        try:
                            # Try to serialize the attribute
                            import json
                            json.dumps(getattr(tool_instance, attr))
                            tool_params[attr] = getattr(tool_instance, attr)
                        except:
                            pass
            
            params_dict['tools'][tool_name] = tool_params
        
        # Process save path using save_params module
        config_path = process_save_path(self.save_params)
        
        # Save parameters if path is valid
        if config_path:
            save_config(params_dict, config_path)
    
    def _generate_processing_report(self, start_time):
        """
        Generate processing report

        Args:
            start_time (float): Start time of processing
        """
        import os
        total_time = time.time() - start_time

        ColorPrinter.print_info("\n" + "=" * 80)
        ColorPrinter.print_info("Processing Summary")
        ColorPrinter.print_info("=" * 80)
        ColorPrinter.print_info(f"Total time: {total_time:.2f} s")
        ColorPrinter.print_info(f"Tools executed: {len(self.processing_history)}")

        if self.processing_history:
            ColorPrinter.print_info("\nTool execution times:")
            for item in self.processing_history:
                tool_name = item['tool']
                exec_time = item['execution_time']
                ColorPrinter.print_info(f"  - {tool_name}: {exec_time:.2f} s")
                if 'quality_change' in item:
                    ColorPrinter.print_info("    Quality changes:")
                    for key, value in item['quality_change'].items():
                        if value != 0:
                            ColorPrinter.print_info(f"      {key}: {value:+.4f}")

        if self.quality_metrics:
            ColorPrinter.print_info("\nQuality metrics comparison:")
            initial_metrics = self.quality_metrics.get('initial', {})
            final_metrics = self.quality_metrics.get('final', {})
            for key in set(initial_metrics.keys()) | set(final_metrics.keys()):
                initial_val = initial_metrics.get(key, 0)
                final_val = final_metrics.get(key, 0)
                change = final_val - initial_val
                ColorPrinter.print_info(f"  - {key}: {initial_val:.4f} → {final_val:.4f} ({change:+.4f})")

        # Save report to file if save_path is provided
        if self.save_path:
            report_path = os.path.join(os.path.dirname(self.save_path), f"processing_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json")
            report_data = {
                'total_time': total_time,
                'tools_executed': len(self.processing_history),
                'processing_history': self.processing_history,
                'quality_metrics': self.quality_metrics,
                'data_shape': list(self.data.shape),
                'feature_count': len(self.data.columns)
            }

            # Create directory if it doesn't exist
            report_dir = os.path.dirname(report_path)
            if report_dir:
                os.makedirs(report_dir, exist_ok=True)

            with open(report_path, 'w', encoding='utf-8') as f:
                json.dump(report_data, f, ensure_ascii=False, indent=2)

            ColorPrinter.print_info(f"Report saved to: {report_path}")
        ColorPrinter.print_info("=" * 80 + "\n")


def main():
    """
    Main function for command-line execution
    """
    import argparse
    import pandas as pd
    
    parser = argparse.ArgumentParser(description='FFE v3.2 Feature Engineering Console')
    parser.add_argument('--data', type=str, required=True, help='Path to input CSV file')
    parser.add_argument('--label', type=str, required=True, help='Label column name')
    parser.add_argument('--output', type=str, default='./clean_data/data00.csv', help='Output file path')
    parser.add_argument('--ways', type=str, default='auto', choices=['auto', 'intelligent', 'pass'], help='Processing way')
    parser.add_argument('--batch-size', type=int, default=None, help='Batch size for large data processing')
    parser.add_argument('--save-params', type=str, default=None, help='Path to save parameters after processing')
    
    args = parser.parse_args()
    
    # Load data
    ColorPrinter.print_info(f"Loading data: {args.data}")
    data = pd.read_csv(args.data)
    ColorPrinter.print_success(f"OK Data loaded successfully: {data.shape}")
    
    # Import preprocessing tools
    try:
        from myffe.preprocessing import NanPreprocessing, OutlierPreprocessing, StrPreprocessing, TimePreprocessing, RelativePreprocessing, SpecifyPreprocessing, SamplePreprocessing, StandardScaler, Normalizer, AutoencoderPreprocessing
    except ImportError as e:
        ColorPrinter.print_error(f"Import error: {e}")
        return
    
    # Create preprocessing tools dictionary
    clean_tools = {
        'nan_preprocessing': NanPreprocessing(shortcut_nan={'nan_ways': []}),
        'autoencoder_preprocessing': AutoencoderPreprocessing(shortcut_autoencoder={'layer': {'layer_1': {'hidden_layers': [5, 10, 5], 'activation': 'relu'}}, 'loss': 'mse', 'epochs': 50, 'batch_size': 32}),
        'outlier_preprocessing': OutlierPreprocessing(shortcut_outlier={'outlier_choice': 'skip'}),
        'str_preprocessing': StrPreprocessing(shortcut_str={'str_choice': 'skip', 'str_cols': []}),
        'time_preprocessing': TimePreprocessing(shortcut_time={'time_col': None}),
        'relative_preprocessing': RelativePreprocessing(shortcut_relative={'choice3_normal': ['skip'], 'choice3_advance': ['skip']}),
        'specify_preprocessing': SpecifyPreprocessing(shortcut_specify={'specify_ways': []}),
        'sample_preprocessing': SamplePreprocessing(shortcut_sample={'choice1_normal': ['skip'], 'choice1_advance': ['skip']}),
        'standard_preprocessing': StandardScaler(),
        'normalized_preprocessing': Normalizer(shortcut_norm='skip')
    }
    
    # Create FFE console
    console = FFE_console(args.label, ways=args.ways, batch_size=args.batch_size, save_params=args.save_params)
    
    # Execute processing
    console(clean_tools, data, save_path=args.output)
    
    ColorPrinter.print_success("FFE processing completed")


if __name__ == "__main__":
    main()
