#这个文件用来写制动评价数据集并且给出路线
import os
import sys
from myffe.tools.color_printer import ColorPrinter

# 添加当前目录到Python路径，以便导入其他模块
current_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(current_dir)

import pandas as pd
import numpy as np

class auto_routes:
    def __init__(self, ways='pandas', tools=None, label_columns=None):
        self.route = {}
        self.ways = ways
        self.label_columns = label_columns  # 标签列
        self.tools = tools  # 要配置的工具列表，如 ['nan_preprocessing', 'outlier_preprocessing']
        
    def __call__(self, path, label_columns=None):
        """主调用函数"""
        self.data = self.read(path)
        # 如果没有提供label_columns，使用初始化时的参数
        if label_columns is None:
            label_columns = self.label_columns
        self.route = self.judge(label_columns)
        return self.route
        
    def read(self, path):
        """这个函数用来读取数据集"""
        if self.ways == 'dask':
            import dask.dataframe as dd
            df = dd.read_csv(path)
            return df.compute()  # 转换为pandas
        elif self.ways == 'pandas':
            return pd.read_csv(path)
        else:
            # 直接使用pandas读取文件
            ColorPrinter.print_info("使用pandas读取CSV文件")
            return pd.read_csv(path)
    def _process_route(self, route_name, tool_name, *args, use_original_data=False, label_columns=None, **kwargs):
        """通用处理方法，简化重复的路由处理逻辑"""
        # 动态导入工具模块
        module = __import__(f'myffe.route.py_tools.{tool_name}', fromlist=[tool_name])
        tool_func = getattr(module, tool_name)
        
        # 选择要传递的数据
        if use_original_data:
            # 传递原始数据（包含标签列）
            data_to_pass = self.data
        else:
            # 分离标签列和特征数据
            if label_columns:
                # 确保label_columns是列表
                if isinstance(label_columns, str):
                    label_columns = [label_columns]
                # 分离特征数据（排除标签列）
                data_to_pass = self.data[[col for col in self.data.columns if col not in label_columns]]
            else:
                data_to_pass = self.data.copy()
        
        # 调用工具函数获取处理参数，传递auto_test=True避免交互式输入
        result = tool_func(data_to_pass, *args, auto_test=True, **kwargs)
        
        # 处理返回结果，确保结构正确
        if isinstance(result, dict):
            # 检查是否已经包含_preprocessing键
            preprocessing_key = f'{route_name}_preprocessing'
            if preprocessing_key in result:
                # 如果已经包含，则直接使用内部的内容
                self.route[preprocessing_key] = result[preprocessing_key]
            else:
                # 否则直接使用结果
                self.route[preprocessing_key] = result
        elif result == 'skip':
            # 如果返回的是'skip'字符串，创建包含'skip'值的默认参数字典
            preprocessing_key = f'{route_name}_preprocessing'
            # 根据工具类型创建对应的默认参数字典
            if route_name == 'nan':
                self.route[preprocessing_key] = {'nan_missing_process_choice': ['skip'], 'nan_processing_col': []}
            elif route_name == 'sample':
                self.route[preprocessing_key] = {'choice1_normal': ['skip'], 'choice1_advance': ['skip']}
            elif route_name == 'time':
                self.route[preprocessing_key] = {'time_col': None}
            elif route_name == 'str':
                self.route[preprocessing_key] = {'str_choice': 'skip', 'str_cols': []}
            elif route_name == 'outlier':
                self.route[preprocessing_key] = {'outlier_choice': 'skip'}
            elif route_name == 'relative':
                self.route[preprocessing_key] = {'choice3_normal': ['skip'], 'choice3_advance': ['skip']}
            elif route_name == 'specify':
                self.route[preprocessing_key] = {'drop_col': [], 'drop_row': []}
            elif route_name == 'standard':
                self.route[preprocessing_key] = {'scaler_method_choice': [], 'standard_col': []}
            elif route_name == 'normalized':
                self.route[preprocessing_key] = {'normalizer_method_choice': [], 'normalized_col': []}
            else:
                # 其他工具类型的默认处理
                self.route[preprocessing_key] = {'choice': 'skip'}
        else:
            # 如果返回的不是字典也不是'skip'，直接存储
            self.route[f'{route_name}_preprocessing'] = result

    def judge(self, label_columns=None):
        """
        这个函数用来评判数据集应该使用哪一些清理方法
        """
        # 初始化路由结构
        self.route = {}
        
        # 定义工具配置，包含路由名称、工具函数名称和参数
        tool_configs = {
            'nan_preprocessing': ('nan', 'nan_py', ()),
            'sample_preprocessing': ('sample', 'sample_py', (label_columns,)),
            'outlier_preprocessing': ('outlier', 'outlier_py', ()),
            'str_preprocessing': ('str', 'str_py', ()),
            'relative_preprocessing': ('relative', 'relative_py', ()),
            'time_preprocessing': ('time', 'time_py', ()),
            'specify_preprocessing': ('specify', 'specify_py', ()),
            'standard_preprocessing': ('standard', 'standard_py', ()),
            'normalized_preprocessing': ('normalized', 'normalized_py', ())
        }
        
        # 按照FFE_config.py中定义的clean_ways顺序调用
        # 如果没有指定工具列表，则执行所有工具
        if self.tools is None:
            # 按顺序执行所有工具
            tools_order = [
                'nan_preprocessing',
                'sample_preprocessing',
                'outlier_preprocessing',
                'str_preprocessing',
                'relative_preprocessing',
                'time_preprocessing',
                'specify_preprocessing',
                'standard_preprocessing',
                'normalized_preprocessing'
            ]
            for tool in tools_order:
                route_name, tool_name, args = tool_configs[tool]
                # 对于sample_preprocessing，需要传递原始数据（包含标签列）
                if tool == 'sample_preprocessing':
                    self._process_route(route_name, tool_name, *args, use_original_data=True, label_columns=label_columns)
                else:
                    self._process_route(route_name, tool_name, *args, label_columns=label_columns)
        else:
            # 只执行指定的工具
            for tool in self.tools:
                if tool in tool_configs:
                    route_name, tool_name, args = tool_configs[tool]
                    # 对于sample_preprocessing，需要传递原始数据（包含标签列）
                    if tool == 'sample_preprocessing':
                        self._process_route(route_name, tool_name, *args, use_original_data=True, label_columns=label_columns)
                    else:
                        self._process_route(route_name, tool_name, *args, label_columns=label_columns)
        
        # 可视化路由数据
        try:
            # 导入visualize_route模块（从tools目录）
            from myffe.tools import visualize_route
            ColorPrinter.print_info("\n" + "=" * 80)
            ColorPrinter.print_info("参数配置可视化")
            ColorPrinter.print_info("=" * 80)
            visualize_route(self.route)
        except ImportError as e:
            ColorPrinter.print_error(f"\n可视化模块未找到: {e}")
            ColorPrinter.print_error("请确保 visualize_route.py 在 tools 目录中")
        
        return self.route
    def get_cleaning_info(self):
        """获取清理信息（只返回路由信息，不执行清理）"""
        import json
        # 返回格式化的JSON字符串，便于阅读
        return json.dumps(self.route, indent=2, ensure_ascii=False)



# 得到的路线的所有的取值

"""
智能推荐参数的取值说明：

1. nan_preprocessing（缺失值处理）
   - nan_missing_process_choice: 每个列的缺失值处理方法列表
     取值：['drop_nan', 'drop_col_high_missing', 'fill_nan_knn', 'fill_nan_mean', 'fill_nan_mode', 'fill_nan_forward', 'fill_nan_intelligent', 'skip']
     默认：所有列为['skip']（当没有缺失值时）
   - nan_processing_col: 缺失值处理的列名列表
     默认：所有列名
   - knn_n_neighbors: KNN填充的邻居数，默认5  

2. sample_preprocessing（采样处理）
   - choice1_normal: 普通模式的采样方法
     取值：['skip', 'multi_class_balance']
     默认：['skip']（当数据平衡时）
   - choice1_advance: 高级模式的采样方法
     取值：['skip', 'MY_high_sample']
     默认：['skip']（当数据平衡时）
   - balance_method: 平衡方法，默认'oversample'
   - random_state: 随机种子，默认42
   - high_sample_selection: 高级采样方法选择
     取值：['RandomOverSampler', 'SMOTE', 'ADASYN', 'BorderlineSMOTE', 'SVMSMOTE', 'EditedNearestNeighbours']
     默认：'RandomOverSampler'
   - smote_k_neighbors: SMOTE的邻居数，默认5
   - adasyn_n_neighbors: ADASYN的邻居数，默认5
   - borderline_smote_k_neighbors: BorderlineSMOTE的邻居数，默认5
   - svm_smote_k_neighbors: SVMSMOTE的邻居数，默认5
   - enn_n_neighbors: EditedNearestNeighbours的邻居数，默认5

3. outlier_preprocessing（异常值处理）
   - outlier_choice: 异常值处理方法
     取值：['skip', 'thres_sigma_auto', 'boxplot', 'isolation_forest', 'multivariate']
     默认：'skip'（当没有异常值或没有数值列时）
   - row_drop_thres: 行异常值阈值，默认3.0
   - auto_drop_row: 是否自动删除异常值行，默认False
   - outlier_action: 异常值处理动作
     取值：['drop', 'replace']
     默认：'drop'
   - contamination: 异常值比例，默认0.1
   - specify_auto_drop_row_extr: 指定异常值检测的列，默认None
   - specify_row: 要删除的列，默认None

4. str_preprocessing（字符串处理）
   - str_choice: 字符串处理方法
     取值：['skip', 'one_hot_encoder', 'label_encoder', 'frequency_encoder']
     默认：'skip'（当没有字符串列时）
   - str_cols: 字符串列，默认空字符串
   - tfidf_min_df: TF-IDF最小文档频率，默认1
   - tfidf_max_df: TF-IDF最大文档频率，默认1.0
   - tfidf_max_features: TF-IDF最大特征数，默认None
   - lda_max_df: LDA最大文档频率，默认1.0
   - lda_min_df: LDA最小文档频率，默认1
   - lda_max_features: LDA最大特征数，默认1000
   - lda_n_components: LDA组件数，默认10
   - lda_random_state: LDA随机种子，默认42
   - use_chinese_tokenizer: 是否使用中文分词，默认False
   - feature_selection: 是否进行特征选择，默认False
   - k_features: 特征选择的特征数，默认100

5. relative_preprocessing（特征工程）
   - clean_type: 清理模式
     取值：['normal', 'advance']
     默认：'normal'
   - choice3_normal: 普通模式的特征工程方法
     取值：['skip', 'linear_plus', 'feature_plus', 'feature_importance']
     默认：['skip']（当没有需要处理的特征时）
   - choice3_advance: 高级模式的特征工程方法
     取值：['skip', 'linear_plus', 'feature_plus', 'pca_lda_kernel', 'feature_importance']
     默认：['skip']（当没有需要处理的特征时）
   - linear_cols: 线性相关列，默认空字符串（当没有数值列时）
   - linear_threshold: 线性相关阈值，默认0.75
   - feature_cols: 特征相关列，默认空字符串（当没有数值列时）
   - feature_threshold: 特征相关阈值，默认0.75
   - relation_func: 关系函数，默认'func1'
   - pca_cols: 降维列，默认空字符串（当没有数值列时）
   - n_components: 降维组件数，默认10
   - kernel_selection: 核选择，默认'pca'
   - n_features: 特征数，默认10

6. time_preprocessing（时间处理）
   - time_col: 时间列，默认None（当没有时间列时）

7. specify_preprocessing（指定删除）
   - drop_col: 要删除的列，默认[]（空列表）
   - drop_row: 要删除的行，默认[]（空列表）

8. standard_preprocessing（标准化）
   - scaler_method_choice: 标准化方法列表
     取值：['Z-score标准化', 'Min-Max标准化', 'MaxAbs标准化', 'RobustScaler标准化']
     默认：[]（空列表，当没有数值列时）
   - standard_col: 标准化列列表
     默认：[]（空列表，当没有数值列时）

9. normalized_preprocessing（归一化）
   - normalizer_method_choice: 归一化方法列表
     取值：['L1归一化', 'L2归一化', 'Max归一化']
     默认：[]（空列表，当没有数值列时）
   - normalized_col: 归一化列列表
     默认：[]（空列表，当没有数值列时）

10. 初始化参数
    - ways: 数据读取方式，默认'pandas'
    - tools: 要配置的工具列表，默认None（执行所有工具）
    - label_columns: 标签列，默认None
"""




# 使用示例
if __name__ == "__main__":
    # 创建测试数据
    import csv
    
    test_data = [
        ["name", "age", "city", "salary", "score", "label"],
        ["Alice", "25", "New York", "50000", "85", "A"],
        ["Bob", "", "Los Angeles", "60000", "90", "B"],  # 空值
        ["", "30", "Chicago", "70000", "75", "A"],        # 空值
        ["David", "35", "", "80000", "80", "C"],          # 空值
        ["Eve", "40", "Boston", "90000", "95", "A"]
    ]
    
    # 写入测试文件
    with open('test.csv', 'w', newline='') as f:
        writer = csv.writer(f)
        writer.writerows(test_data)
    
    # 使用auto_routes
    auto_route = auto_routes(ways='cpp')
    route = auto_route('test.csv')
    
    ColorPrinter.print_info("清理路线:")
    if 'specify_preprocessing' in route:
        if 'drop_row' in route['specify_preprocessing']:
            ColorPrinter.print_info(f"要删除的行: {route['specify_preprocessing']['drop_row']}")
        if 'drop_col' in route['specify_preprocessing']:
            ColorPrinter.print_info(f"要删除的列: {route['specify_preprocessing']['drop_col']}")
    if 'nan_preprocessing' in route:
        ColorPrinter.print_info(f"缺失值处理方法: {route['nan_preprocessing'].get('nan_missing_process_choice', 'None')}")
    
    if 'standard_preprocessing' in route:
        ColorPrinter.print_info("\n标准化路线:")
        standard_col = route['standard_preprocessing']['standard_col']
        ColorPrinter.print_info(f"标准化列: {standard_col}")
        ColorPrinter.print_info("标准化方法:")
        methods = route['standard_preprocessing']['scaler_method_choice']
        for col, method in zip(standard_col, methods):
            ColorPrinter.print_info(f"  {col}: {method}")
    
    if 'normalized_preprocessing' in route:
        ColorPrinter.print_info("\n归一化路线:")
        normalized_col = route['normalized_preprocessing']['normalized_col']
        ColorPrinter.print_info(f"归一化列: {normalized_col}")
        ColorPrinter.print_info("归一化方法:")
        methods = route['normalized_preprocessing']['normalizer_method_choice']
        for col, method in zip(normalized_col, methods):
            ColorPrinter.print_info(f"  {col}: {method}")
    
    if 'sample_preprocessing' in route:
        ColorPrinter.print_info("\n采样处理路线:")
        sample_info = route['sample_preprocessing']
        ColorPrinter.print_info("采样参数配置:")
        for key, value in sample_info.items():
            ColorPrinter.print_info(f"    {key}: {value}")
    
    # 获取清理信息（不执行清理）
    cleaning_info = auto_route.get_cleaning_info()
    ColorPrinter.print_info("\n清理信息:")
    ColorPrinter.print_info(cleaning_info)
    
    # 可视化路由数据已在 judge 方法中调用，此处不再重复
    # try:
    #     from visualize_route import visualize_route
    #     print("\n" + "=" * 80)
    #     print("正在生成可视化表格...")
    #     print("=" * 80)
    #     visualize_route(route)
    # except ImportError:
    #     print("\n可视化模块未找到，请确保 visualize_route.py 在同一目录")



#  a  = {  
#     b =  []
#     c = []
# }
