import sys
import os

# 添加项目根目录到Python路径
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..')))

from myffe.tools.Loggerv1_1 import log_class
from myffe.tools.color_printer import ColorPrinter
from myffe.tools.data_inspector import inspect_data
from myffe.tools.len_match import len_match
from myffe.tools.evaluation_decorator import with_evaluation
import pandas as pd
import numpy as np



@log_class(type='use')
class StandardScaler:
    def __init__(self, shortcut_stand=None):
        self.shortcut_stand = shortcut_stand
    
    @with_evaluation
    def __call__(self, data):
        return self.MY_StandardScaler(data, stand_params=self.shortcut_stand)
    
    def MY_StandardScaler(self, data, stand_params=None):
        # 检查是否为'skip'
        if stand_params == 'skip':
            ColorPrinter.print_info('Skipping standardization as it is configured to "skip"')
            return data
        
        # 检查stand_params是否为None
        if stand_params is None:
            ColorPrinter.print_warning('标准化参数为None，返回原始数据')
            return data
        
        # 使用新的 standard_ways 格式
        if 'standard_ways' in stand_params:
            return self._process_with_standard_ways(data, stand_params['standard_ways'])
        else:
            ColorPrinter.print_warning('未指定标准化方式，返回原始数据')
            return data
    
    def _process_with_standard_ways(self, data, standard_ways):
        """使用新的 standard_ways 格式处理标准化"""
        try:
            # 导入sklearn模块
            from sklearn.preprocessing import StandardScaler as SklearnStandardScaler, MinMaxScaler, MaxAbsScaler, RobustScaler, QuantileTransformer
            # 创建数据副本
            scaled_data = data.copy()
            
            # 如果没有指定列，跳过处理
            if not standard_ways :
                ColorPrinter.print_warning('未指定标准化列，跳过标准化处理')
                return scaled_data
            
            # 对每列应用对应的标准化方法
            for item in standard_ways:
                col = item.get('col')
                method = item.get('method')

                if col in data.columns:
                    if method == 'skip':
                        ColorPrinter.print_progress(f'跳过列 {col} 的标准化处理')
                        continue
                    elif method == 'Z-score标准化':
                        ColorPrinter.print_progress(f'对列 {col} 使用 {method}')
                        scaler = SklearnStandardScaler()
                        scaled_data[[col]] = pd.DataFrame(
                            scaler.fit_transform(scaled_data[[col]]),
                            columns=[col],
                            index=scaled_data.index
                        )
                    elif method == 'Min-Max标准化':
                        ColorPrinter.print_progress(f'对列 {col} 使用 {method}')
                        scaler = MinMaxScaler()
                        scaled_data[[col]] = pd.DataFrame(
                            scaler.fit_transform(scaled_data[[col]]),
                            columns=[col],
                            index=scaled_data.index
                        )
                    elif method == 'MaxAbs标准化':
                        ColorPrinter.print_progress(f'对列 {col} 使用 {method}')
                        scaler = MaxAbsScaler()
                        scaled_data[[col]] = pd.DataFrame(
                            scaler.fit_transform(scaled_data[[col]]),
                            columns=[col],
                            index=scaled_data.index
                        )
                    elif method == 'RobustScaler标准化':
                        ColorPrinter.print_progress(f'对列 {col} 使用 {method}')
                        scaler = RobustScaler()
                        scaled_data[[col]] = pd.DataFrame(
                            scaler.fit_transform(scaled_data[[col]]),
                            columns=[col],
                            index=scaled_data.index
                        )
                    elif method == 'QuantileTransformer标准化':
                        ColorPrinter.print_progress(f'对列 {col} 使用 {method}')
                        scaler = QuantileTransformer(output_distribution='uniform')
                        scaled_data[[col]] = pd.DataFrame(
                            scaler.fit_transform(scaled_data[[col]]),
                            columns=[col],
                            index=scaled_data.index
                        )
                    elif method == '均值归一化':
                        ColorPrinter.print_progress(f'对列 {col} 使用 {method}')
                        mean_val = scaled_data[col].mean()
                        scaled_data[col] = scaled_data[col] - mean_val
                    elif method == '单位长度归一化':
                        ColorPrinter.print_progress(f'对列 {col} 使用 {method}')
                        norm = np.linalg.norm(scaled_data[col])
                        if norm > 0:
                            scaled_data[col] = scaled_data[col] / norm
                    elif method == '自定义缩放':
                        ColorPrinter.print_progress(f'对列 {col} 使用 {method}')
                        mean_val = scaled_data[col].mean()
                        std_val = scaled_data[col].std()
                        if std_val > 0:
                            scaled_data[col] = (scaled_data[col] - mean_val) / (2 * std_val)  # 缩放到[-0.5, 0.5]范围
                    else:
                        ColorPrinter.print_error(f'标准化方法 {method} 无效')
                else:
                    ColorPrinter.print_error(f'列 {col} 不存在')
                    continue
            
            return scaled_data
        except Exception as e:
            ColorPrinter.print_error(f'标准化过程出错: {e}')
            return data
    



"""
参数说明文档:

shortcut_stand 参数字典:
    - standard_ways: 标准化配置列表
      类型: 列表
      元素类型: 字典
      默认值: 无（必须指定）
      说明: 为每列指定标准化方法
      字典结构:
        {
            'col': '列名',  # 要标准化的列名
            'method': '标准化方法'  # 标准化方法名称
        }
      可选的标准化方法:
        - 'Z-score标准化': 标准化到均值为0，标准差为1的分布，适用于正态分布数据
        - 'Min-Max标准化': 将数据缩放到[0,1]区间，适用于有明显边界的数据
        - 'MaxAbs标准化': 将数据缩放到[-1,1]区间，适用于包含负值的数据
        - 'RobustScaler标准化': 使用中位数和四分位数进行缩放，对异常值不敏感
        - 'QuantileTransformer标准化': 将数据映射到均匀分布，适用于非正态分布数据
        - '均值归一化': 减去均值，使数据围绕0中心分布
        - '单位长度归一化': 缩放到单位范数，适用于需要保持方向的场景
        - '自定义缩放': 根据数据特性自定义缩放，这里缩放到[-0.5, 0.5]范围
        - 'skip': 跳过该列的标准化处理

使用示例:
    # 为不同列应用不同的标准化方法
    stand_params = {
        'standard_ways': [
            {'col': 'feature1', 'method': 'Z-score标准化'},
            {'col': 'feature2', 'method': 'Min-Max标准化'},
            {'col': 'feature3', 'method': 'RobustScaler标准化'},
            {'col': 'feature4', 'method': 'skip'}  # 跳过该列
        ]
    }
    scaler = StandardScaler(shortcut_stand=stand_params)
    scaled_data = scaler(data)

    # 或者使用 'skip' 跳过整个标准化处理
    skip_scaler = StandardScaler(shortcut_stand='skip')
    original_data = skip_scaler(data)
"""


if __name__ == "__main__":
    import pandas as pd
    import numpy as np
    
    print("=" * 60)
    print("标准化处理测试程序")
    print("=" * 60)
    
    # 创建测试数据（包含一些异常值）
    np.random.seed(42)
    test_data = pd.DataFrame({
        'feature1': np.random.normal(50, 10, 20),
        'feature2': np.random.normal(100, 20, 20),
        'feature3': np.random.normal(200, 30, 20)
    })
    
    # 添加一些异常值
    test_data.loc[0, 'feature1'] = 150
    test_data.loc[1, 'feature2'] = 300
    test_data.loc[2, 'feature3'] = 500
    
    print("\n原始数据:")
    print(test_data)
    print("\n数据统计:")
    print(test_data.describe())
    
    # 测试为不同列应用不同的标准化方法
    print(f"\n{'=' * 60}")
    print("测试: 为不同列应用不同的标准化方法")
    print('=' * 60)
    
    stand_params = {
        'standard_ways': [
            {'col': 'feature1', 'method': 'Z-score标准化'},
            {'col': 'feature2', 'method': 'Min-Max标准化'},
            {'col': 'feature3', 'method': 'RobustScaler标准化'}
        ]
    }
    
    scaler = StandardScaler(shortcut_stand=stand_params)
    scaled_data = scaler(test_data.copy())
    
    print("\n标准化后的数据:")
    print(scaled_data)
    print("\n标准化后数据统计:")
    print(scaled_data.describe())
    
    print("\n" + "=" * 60)
    print("测试完成！")
    print("=" * 60)
    
    # 深度渗透测试套件
    print(f"\n{'=' * 80}")
    print("深度渗透测试套件")
    print('=' * 80)
    
    # 创建更大的测试数据
    np.random.seed(42)
    large_test_data = pd.DataFrame({
        'feature1': np.random.normal(50, 10, 1000),
        'feature2': np.random.normal(100, 20, 1000),
        'feature3': np.random.normal(200, 30, 1000),
        'feature4': np.random.normal(300, 40, 1000),
        'feature5': np.random.normal(400, 50, 1000)
    })
    
    # 添加一些异常值
    large_test_data.loc[0, 'feature1'] = 500
    large_test_data.loc[1, 'feature2'] = 1000
    large_test_data.loc[2, 'feature3'] = 2000
    large_test_data.loc[3, 'feature4'] = 3000
    large_test_data.loc[4, 'feature5'] = 4000
    
    # 测试1: 边界条件测试 - 空参数
    print(f"\n{'-' * 60}")
    print("测试1: 边界条件测试 - 空参数")
    print('-' * 60)
    
    stand_processor_1 = StandardScaler(shortcut_stand={})
    result_1 = stand_processor_1(large_test_data.copy())
    
    print(f"\n数据形状变化: {large_test_data.shape} -> {result_1.shape}")
    print("期望：数据保持不变")
    
    # 测试2: 边界条件测试 - 不存在的列
    print(f"\n{'-' * 60}")
    print("测试2: 边界条件测试 - 不存在的列")
    print('-' * 60)
    
    params_nonexistent_col = {
        'standard_ways': [
            {'col': 'nonexistent_col', 'method': 'Z-score标准化'},
            {'col': 'feature1', 'method': 'Z-score标准化'}
        ]
    }
    stand_processor_2 = StandardScaler(shortcut_stand=params_nonexistent_col)
    result_2 = stand_processor_2(large_test_data.copy())
    
    print(f"\n数据形状变化: {large_test_data.shape} -> {result_2.shape}")
    print("期望：只对存在的 feature1 进行标准化")
    
    # 测试3: 边界条件测试 - 单一方法应用到所有列
    print(f"\n{'-' * 60}")
    print("测试3: 边界条件测试 - 单一方法应用到所有列")
    print('-' * 60)
    
    params_single_method = {
        'standard_ways': [
            {'col': 'feature1', 'method': 'Min-Max标准化'},
            {'col': 'feature2', 'method': 'Min-Max标准化'},
            {'col': 'feature3', 'method': 'Min-Max标准化'}
        ]
    }
    stand_processor_3 = StandardScaler(shortcut_stand=params_single_method)
    result_3 = stand_processor_3(large_test_data.copy())
    
    print(f"\n处理后数据统计:")
    print(result_3[['feature1', 'feature2', 'feature3']].describe())
    print("期望：所有列的范围在 [0, 1] 之间")
    
    # 测试4: 边界条件测试 - 方法和列数量不匹配
    print(f"\n{'-' * 60}")
    print("测试4: 边界条件测试 - 方法和列数量不匹配")
    print('-' * 60)
    
    params_mismatch = {
        'standard_ways': [
            {'col': 'feature1', 'method': 'Z-score标准化'},
            {'col': 'feature2', 'method': 'Min-Max标准化'}
        ]
    }
    stand_processor_4 = StandardScaler(shortcut_stand=params_mismatch)
    result_4 = stand_processor_4(large_test_data.copy())
    
    print(f"\n数据形状变化: {large_test_data.shape} -> {result_4.shape}")
    print("期望：只对前两列进行处理，第三列保持不变")
    
    # 测试5: 边界条件测试 - 空列列表
    print(f"\n{'-' * 60}")
    print("测试5: 边界条件测试 - 空列列表")
    print('-' * 60)
    
    params_empty_cols = {
        'standard_ways': []
    }
    stand_processor_5 = StandardScaler(shortcut_stand=params_empty_cols)
    result_5 = stand_processor_5(large_test_data.copy())
    
    print(f"\n数据形状变化: {large_test_data.shape} -> {result_5.shape}")
    print("期望：数据保持不变")
    
    # 测试6: 组合测试 - 所有方法依次应用
    print(f"\n{'-' * 60}")
    print("测试6: 组合测试 - 所有方法依次应用")
    print('-' * 60)
    
    methods = ['Z-score标准化', 'Min-Max标准化', 'MaxAbs标准化', 'RobustScaler标准化']
    cols = ['feature1', 'feature2', 'feature3', 'feature4']
    
    params_all_methods = {
        'standard_ways': [{'col': col, 'method': method} for col, method in zip(cols, methods)]
    }
    stand_processor_6 = StandardScaler(shortcut_stand=params_all_methods)
    result_6 = stand_processor_6(large_test_data.copy())
    
    print(f"\n处理后数据统计:")
    print(result_6.describe())
    print(f"\n期望：feature1 Z-score标准化（均值≈0, 标准差≈1）")
    print(f"期望：feature2 Min-Max标准化（范围[0,1]）")
    print(f"期望：feature3 MaxAbs标准化（范围[-1,1]）")
    print(f"期望：feature4 RobustScaler标准化（对异常值不敏感）")
    
    # 测试7: 大量数据测试
    print(f"\n{'-' * 60}")
    print("测试7: 大量数据测试")
    print('-' * 60)
    
    huge_test_data = pd.DataFrame({
        'col1': np.random.normal(0, 1, 10000),
        'col2': np.random.normal(10, 5, 10000),
        'col3': np.random.normal(100, 20, 10000)
    })
    
    params_huge = {
        'standard_ways': [
            {'col': 'col1', 'method': 'Z-score标准化'},
            {'col': 'col2', 'method': 'Min-Max标准化'},
            {'col': 'col3', 'method': 'RobustScaler标准化'}
        ]
    }
    
    stand_processor_7 = StandardScaler(shortcut_stand=params_huge)
    result_7 = stand_processor_7(huge_test_data.copy())
    
    print(f"\n处理前数据形状: {huge_test_data.shape}")
    print(f"处理后数据形状: {result_7.shape}")
    print(f"处理后数据统计:")
    print(result_7.describe())
    print("期望：所有列成功标准化，没有错误")
    
    # 测试8: 重复列测试
    print(f"\n{'-' * 60}")
    print("测试8: 重复列测试")
    print('-' * 60)
    
    params_duplicate = {
        'standard_ways': [
            {'col': 'feature1', 'method': 'Z-score标准化'},
            {'col': 'feature1', 'method': 'Min-Max标准化'}
        ]
    }
    stand_processor_8 = StandardScaler(shortcut_stand=params_duplicate)
    result_8 = stand_processor_8(large_test_data.copy())
    
    print(f"\n数据形状变化: {large_test_data.shape} -> {result_8.shape}")
    print("期望：feature1 被处理两次，最终是第二次的 Min-Max 标准化结果")
    
    # 测试9: 单一列测试
    print(f"\n{'-' * 60}")
    print("测试9: 单一列测试")
    print('-' * 60)
    
    params_single_col = {
        'standard_ways': [
            {'col': 'feature1', 'method': 'RobustScaler标准化'}
        ]
    }
    stand_processor_9 = StandardScaler(shortcut_stand=params_single_col)
    result_9 = stand_processor_9(large_test_data.copy())
    
    print(f"\nfeature1 处理前后统计对比:")
    print("处理前:")
    print(large_test_data['feature1'].describe())
    print("\n处理后:")
    print(result_9['feature1'].describe())
    print("期望：feature1 使用 RobustScaler 标准化，对异常值不敏感")
    
    # 测试10: 验证标准化结果
    print(f"\n{'-' * 60}")
    print("测试10: 验证标准化结果")
    print('-' * 60)
    
    test_data_verify = pd.DataFrame({
        'col': np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
    })
    
    params_verify = {
        'standard_ways': [
            {'col': 'col', 'method': 'Min-Max标准化'}
        ]
    }
    
    stand_processor_10 = StandardScaler(shortcut_stand=params_verify)
    result_10 = stand_processor_10(test_data_verify.copy())
    
    print(f"\n原始数据: {test_data_verify['col'].tolist()}")
    print(f"Min-Max标准化后: {result_10['col'].round(2).tolist()}")
    print("期望：范围应该在 [0, 1] 之间，最小值为 0，最大值为 1")
    
    print(f"\n{'=' * 80}")
    print("深度渗透测试完成！")
    print('=' * 80)
