#!/usr/bin/env python3
"""
Visualize Route Tool
Used to visualize the structure of feature engineering routes
"""

import sys
import os

# Add MFM root directory to Python path
current_dir = os.path.dirname(os.path.abspath(__file__))
ffe_dir = os.path.dirname(current_dir)
mfm_dir = os.path.dirname(os.path.dirname(ffe_dir))
sys.path.append(mfm_dir)

# Import color_printer module
from myffe.tools.color_printer import ColorPrinter

def cprint(text, color=None,bold=False):     #this is the color print switch
    """Print text with color"""
    if color == 'header':
        ColorPrinter.print_info(text)
    elif color == 'okblue':
        ColorPrinter.print_info(text)
    elif color == 'okgreen':
        ColorPrinter.print_success(text)
    elif color == 'warning':
        ColorPrinter.print_warning(text)
    elif color == 'fail':
        ColorPrinter.print_error(text)
    else:
        print(text)

def print_tree(data, indent=0, prefix=""):   #this is the tree-style print,those codes are written perfectly
    """
    Print data structure as tree
    
    Args:
        data: Data structure to visualize
        indent: Indentation level
        prefix: Prefix string          
    """
    if isinstance(data, dict): 
        for i, (key, value) in enumerate(data.items()):
            is_last = i == len(data) - 1
            connector = "└── " if is_last else "├── "    #check if it is the last one ,if so,use "└── " else use "├── "
            if isinstance(value, (dict, list)):
                cprint(f"{prefix}{connector}{key}", "okblue")
                new_prefix = prefix + ("    " if is_last else "│   ")
                print_tree(value, indent + 1, new_prefix)    #recursively print the tree-style print
            else:
                cprint(f"{prefix}{connector}{key}: {value}", "okgreen")
    elif isinstance(data, list):
        for i, item in enumerate(data):
            is_last = i == len(data) - 1
            connector = "└── " if is_last else "├── "
            if isinstance(item, (dict, list)):
                cprint(f"{prefix}{connector}[{i}]", "okblue")
                new_prefix = prefix + ("    " if is_last else "│   ")
                print_tree(item, indent + 1, new_prefix)
            else:
                cprint(f"{prefix}{connector}{item}", "okgreen")

def print_section_title(title, section_number=None):
    """Print section title"""
    if section_number:
        cprint(f"\n{section_number}. {title}", "header", bold=True)
    else:
        cprint(f"\n{title}", "header", bold=True)
    cprint("-" * 40, "header")

def print_detailed_params(data, indent=2):
    """
    Print detailed parameters
    
    Args:
        data: Parameter data
        indent: Indentation level
    """
    if isinstance(data, dict):
        for key, value in data.items():
            if isinstance(value, (dict, list)):
                cprint(f"{' ' * indent}• {key}:", "okblue")
                print_detailed_params(value, indent + 4)
            else:
                cprint(f"{' ' * indent}• {key}: {value}", "okgreen")
    elif isinstance(data, list):
        for i, item in enumerate(data):
            if isinstance(item, (dict, list)):
                cprint(f"{' ' * indent}• [{i}]:", "okblue")
                print_detailed_params(item, indent + 4)
            else:
                cprint(f"{' ' * indent}• {item}", "okgreen")

def visualize_route(route):
    """
    Visualize the structure of feature engineering route
    
    Args:
        route: Feature engineering route
    """
    cprint("=" * 80, "header", bold=True)  # display in bold
    cprint("Route Visualization (Tree View)", "header", bold=True)  
    cprint("=" * 80, "header", bold=True)
    
    # Print route structure
    print_tree(route)
    
    cprint("\n" + "=" * 80, "header", bold=True)
    cprint("Route Details", "header", bold=True)
    cprint("=" * 80, "header", bold=True)
    
    # Statistics
    total_modules = len(route)
    cprint(f"\n• Summary: Found {total_modules} processing modules", "okblue", bold=True)
    
    # Module name mapping
    module_names = {
        'nan_preprocessing': 'Missing Value Processing',
        'standard_preprocessing': 'Standardization',
        'normalized_preprocessing': 'Normalization',
        'sample_preprocessing': 'Sampling',
        'outlier_preprocessing': 'Outlier Detection',
        'str_preprocessing': 'String Processing',
        'relative_preprocessing': 'Relative Features',
        'time_preprocessing': 'Time Processing',
        'specify_preprocessing': 'Specified Processing'
    }
    
    section_count = 1
    for module_key, module_data in route.items():
        # Get module name
        module_name = module_names.get(module_key, module_key)
        print_section_title(module_name, section_count)
        
        # Print module parameters
        print_detailed_params(module_data)
        section_count += 1
    
    cprint("\n" + "=" * 80, "header", bold=True)
    cprint("Visualization Complete", "okgreen", bold=True)
    cprint("=" * 80, "header", bold=True)


if __name__ == "__main__":
    # Test data
    test_route = {
        "nan_preprocessing": {
            "nan_missing_process_choice": [["skip"], ["skip"], ["skip"]],
            "nan_processing_col": ["name", "age", "salary"],
            "drop_threshold": 0.5,
            "knn_n_neighbors": 5
        },
        "standard_preprocessing": {
            "scaler_method_choice": ["Z-score Standardization", "RobustScaler Standardization", "RobustScaler Standardization"],
            "standard_col": ["age", "salary", "score"]
        },
        "normalized_preprocessing": {
            "normalizer_method_choice": ["Max Normalization", "Max Normalization", "Max Normalization"],
            "normalized_col": ["age", "salary", "score"]
        },
        "sample_preprocessing": {
            "choice1_normal": ["multi_class_balance"],
            "choice1_advance": ["skip"],
            "balance_method": "oversample",
            "random_state": 42,
            "high_sample_selection": "RandomOverSampler"
        }
    }
    
    visualize_route(test_route)



# A traditional terminal width is 80 characters, so there is set the width to 80 characters
