# Python 实现的归一化评价函数
import numpy as np
import pandas as pd

# 导入所需模块
import sys
import os

# 添加MFM目录到路径
current_dir = os.path.dirname(os.path.abspath(__file__))
# py_tools -> route -> FFEv3_2 -> FFE -> MFM -> 根目录
root_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))))
if root_dir not in sys.path:
    sys.path.append(root_dir)

from myffe.tools.interactive import interactive
from myffe.tools.color_printer import ColorPrinter
from myffe.tools.len_match import len_match
from myffe.tools.visualize_route import visualize_route
from myffe.tools.interactive_utils import get_interactive_choice

from myffe.route.tools_py.normalizer_selector import get_best_normalizer, is_numeric_columns

def analyze_normalization(data, auto_test=False):
    """分析数据的归一化需求，为每列推荐适合的归一化方法
    
    Args:
        data: pandas DataFrame，输入数据
        auto_test: bool，是否自动测试模式，默认为 False
    
    Returns:
        dict: 包含归一化参数的字典，使用嵌套字典列表结构
    """
    normalized_preprocessing = {
        'normalized_ways': []  # 存储每个列的归一化配置
    }

    normalizer_methods = ['L1 Normalization', 'L2 Normalization', 'Max Normalization', 'Robust Normalization', 'Power Normalization', 'Log Normalization', 'Square Root Normalization', 'skip']
    
    # 筛选出数值列
    numeric_columns = []
    for col in data.columns:
        # 检查是否为数值列
        col_data = data[col].astype(str).tolist()
        if not col_data or all(val == '' for val in col_data):
            continue
        if is_numeric_columns(col_data):
            numeric_columns.append(col)
    
    if not numeric_columns:
        ColorPrinter.print_info("数据中没有需要归一化的数值列")
        return {'normalized_preprocessing': 'skip'}
    
    inter_normalized = get_interactive_choice(
        title="智能推荐？",
        description="选择'ok'将自动为所有数值列推荐最佳归一化方法，选择'no'需要手动选择",
        auto_test=auto_test
    )
    
    if not inter_normalized:
        while True:
            # 重置参数列表
            normalized_preprocessing['normalized_ways'] = []
            
            selected_cols = interactive(numeric_columns, title="请按上下箭头选择，回车确认归一化处理列,点击'm'键进行多选择", description="选择要进行归一化处理的列，可以多选", min_select=1, max_select=len(numeric_columns)).run()
            # 确保返回值是列表
            selected_cols = selected_cols if isinstance(selected_cols, list) else [selected_cols]
            ColorPrinter.print_success('你已选择归一化处理列：' + str(selected_cols))
            
            # 为每列选择归一化方法
            for col in selected_cols:
                selected_method = interactive(normalizer_methods, title=f"请按上下箭头选择，回车确认{col}的归一化方法", description="L1归一化:基于曼哈顿距离, L2归一化:基于欧几里得距离, Max归一化:基于最大值缩放, Robust归一化:对异常值不敏感, 幂次归一化:适合偏度较大的数据, 对数归一化:适合取值范围大的正数数据, 平方根归一化:适合非负数据, 跳过:不进行归一化处理", min_select=1, max_select=1).run()
                # 确保返回值是单个字符串
                method = selected_method[0]
                # 为当前列创建归一化配置
                col_config = {
                    'col': col,
                    'method': method
                }
                normalized_preprocessing['normalized_ways'].append(col_config)
                ColorPrinter.print_success(f'你已选择{col}的归一化方法：{method}')
            
            break
    else:
        # 智能推荐模式
        for col in numeric_columns:
            col_data = data[col].astype(str).tolist()
            best_method = get_best_normalizer(col_data)
            # 为当前列创建归一化配置
            col_config = {
                'col': col,
                'method': best_method
            }
            normalized_preprocessing['normalized_ways'].append(col_config)
            ColorPrinter.print_info(f"为列 '{col}' 推荐归一化方法：{best_method}")
    
    # 不再过滤跳过的列，保留所有列的配置信息
    # 这样即使选择了 'skip'，列的信息也会被保留在配置中
    
    result = {
        'normalized_preprocessing': normalized_preprocessing
    }
    visualize_route(result)
    return result

def normalized_py(data, auto_test=False):
    """使用Python实现为每一列确定最佳归一化方法
    
    Args:
        data: pandas DataFrame，输入数据
        auto_test: bool，是否自动测试模式，默认为 False
    
    Returns:
        dict: 包含归一化参数的字典
    """
    return analyze_normalization(data, auto_test=auto_test)

if __name__ == "__main__":
    # 测试代码
    import pandas as pd
    import numpy as np
    
    # 创建测试数据
    np.random.seed(42)
    data = pd.DataFrame({
        'numeric_col1': np.random.normal(100, 10, 20),
        'numeric_col2': np.random.normal(50, 5, 20),
        'numeric_col3': np.random.uniform(0, 100, 20)
    })
    
    ColorPrinter.print_info("测试数据:")
    ColorPrinter.print_any(data.head(), color='white')
    ColorPrinter.print_any("\n数据统计:", color='blue')
    ColorPrinter.print_any(data.describe(), color='white')
    
    # 测试归一化处理
    ColorPrinter.print_info("\n测试归一化处理:")
    result = normalized_py(data)
    ColorPrinter.print_success("处理结果:")
    ColorPrinter.print_any(result, color='white')




"""
这个文件输入一个data
输出一个字典
格式是：
{
    'normalized_preprocessing': {
        'normalized_ways': [
            {
                'col': 'col1',
                'method': 'L1 Normalization'
            },
            {
                'col': 'col2',
                'method': 'L2 Normalization'
            }
        ]
    }
}

method的取值有
    'L1 Normalization'   # L1 Normalization
    'L2 Normalization'   # L2 Normalization
    'Max Normalization'   # Max Normalization
    'Robust Normalization'   # Robust Normalization, not sensitive to outliers
    'Power Normalization'   # Power Normalization, suitable for data with large skewness
    'Log Normalization'   # Log Normalization, suitable for positive data with large range
    'Square Root Normalization'   # Square Root Normalization, suitable for non-negative data
    'skip'   # Skip normalization

参数处理逻辑：
- 每个列的归一化配置是独立的，包含在normalized_ways列表中的一个字典里
- 这种设计与nan处理的配置格式保持一致，提高了代码的一致性和可维护性
"""

