import pandas as pd
import numpy as np
from scipy import stats

import sys
import os

current_dir = os.path.dirname(os.path.abspath(__file__))
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.visualize_route import visualize_route
from myffe.tools.interactive_utils import get_interactive_choice
from myffe.route.tools_py.outlier_detector import is_numeric_columns, detect_outliers_iqr, detect_outliers_zscore

# 异常值分析主函数

def analyze_outlier_distribution(data, auto_test=False):
    """分析数据的异常值分布，为异常值处理提供参数
    
    Args:
        data: pandas DataFrame，输入数据
        auto_test: bool，是否自动测试模式，默认为 False
    
    Returns:
        dict: 包含异常值处理参数的字典
    """
    # 初始化异常值处理参数
    outlier_params = {
        'outlier_choice': 'multivariate',
        'row_drop_thres': 3.0,
        'auto_drop_row': False,
        'outlier_action': 'drop',
        'contamination': 0.1,
        'specify_auto_drop_row_extr': None,
        'specify_row': None
    }

    # 筛选数值列
    numeric_columns = []
    for col in data.columns:
        col_data = data[col].astype(str).tolist()
        if is_numeric_columns(col_data):
            numeric_columns.append(col)

    # 检查是否有数值列
    if not numeric_columns:
        ColorPrinter.print_warning("数据中没有数值列")
        return {'outlier_preprocessing': 'skip'}

#region 检测异常值，并且得到异常值列
    has_outliers = False
    outlier_columns = []
    for col in numeric_columns:  # 遍历数值列并检测异常值
        try:
            data[col] = pd.to_numeric(data[col])
            if detect_outliers_iqr(data, col) or detect_outliers_zscore(data, col):
                has_outliers = True
                outlier_columns.append(col)
        except ValueError:
            continue
#endregion

    #region 检查是否有异常值
    if not has_outliers:
        ColorPrinter.print_info("数据中未检测到异常值")
        return {'outlier_preprocessing': 'skip'}
    ColorPrinter.print_success(f"检测到异常值列：{outlier_columns}")
    #endregion 检查是否有异常值

    # 获取智能推荐选择
    inter_outlier = get_interactive_choice(
        title="智能推荐？",
        description="选择'ok'将自动推荐最佳异常值处理方法，选择'no'需要手动选择",
        auto_test=auto_test
    )

    # 智能推荐模式
    if inter_outlier:
        data_size = len(data)
        num_features = len(numeric_columns)

        # 根据数据特征选择最佳异常值检测方法
        if num_features == 1:
            outlier_choice = 'thres_sigma_auto'
        elif num_features >= 2 and data_size > 100:
            outlier_choice = 'multivariate'
        elif data_size > 1000:
            outlier_choice = 'boxplot'
        else:
            outlier_choice = 'isolation_forest'

        outlier_params['outlier_choice'] = outlier_choice
        outlier_params['outlier_action'] = 'drop'

        # 根据选择的方法设置相应参数
        if outlier_choice == 'thres_sigma_auto':
            outlier_params['row_drop_thres'] = 3.0
            outlier_params['specify_auto_drop_row_extr'] = 'auto'
        elif outlier_choice in ['isolation_forest', 'multivariate']:
            outlier_params['contamination'] = 0.1
        elif outlier_choice == 'boxplot':
            pass

        ColorPrinter.print_info(f"智能推荐方法：{outlier_choice}")
        ColorPrinter.print_info(f"智能推荐动作：{outlier_params['outlier_action']}")
    else:
        # 手动选择模式
        outlier_choices = [
            'thres_sigma_auto',
            'boxplot',
            'isolation_forest',
            'multivariate',
            'skip'
        ]
        selected = interactive(
            outlier_choices,
            title="请选择异常值处理方法",
            description="thres_sigma_auto:基于标准差, boxplot:箱线图, isolation_forest:孤立森林, multivariate:多变量检测, skip:跳过",
            min_select=1, max_select=1
        ).run()

        outlier_params['outlier_choice'] = selected[0]

    outlier_choice = outlier_params['outlier_choice']

#region 处理跳过选择
    if outlier_choice == 'skip':
        ColorPrinter.print_info("跳过异常值处理")
        return {'outlier_preprocessing': 'skip'}
#endregion 
    # 手动设置参数
    if not inter_outlier:
#region 选择异常值处理动作: outlier_action
        outlier_action_choices = ['drop', 'replace']
        selected_action = interactive(
            outlier_action_choices,
            title="请选择异常值处理动作",
            description="drop:删除异常值行, replace:替换异常值",
            min_select=1, max_select=1
        ).run()
        outlier_params['outlier_action'] = selected_action[0]
#endregion 选择异常值处理动作
#region 设置标准差倍数阈值: row_drop_thres
        if outlier_choice == 'thres_sigma_auto':
            threshold_options = ['1.0', '2.0', '2.5', '3.0', '3.5', '4.0']
            selected_thres = interactive(
                threshold_options,
                title="请选择标准差倍数阈值",
                description="用于判断异常值的阈值倍数，值越小检测越严格",
                min_select=1, max_select=1
            ).run()
            outlier_params['row_drop_thres'] = float(selected_thres[0])
        else:
            outlier_params['row_drop_thres'] = 3.0
#region 选择是否指定检测列: specify_auto_drop_row_extr
        # 选择是否指定检测列
        ColorPrinter.print_info("是否指定检测列？")
        specify_col_choice = interactive(
            ['auto', '手动选择', '不指定'],
            title="请选择",
            description="auto:对所有数值列检测, 手动选择:选择特定列, 不指定:不指定列",
            min_select=1, max_select=1
        ).run()

        if specify_col_choice[0] == '手动选择':
            selected_cols = interactive(
                numeric_columns,
                title="请选择要检测的列",
                description="选择要进行异常值检测的列，可多选",
                min_select=1, max_select=len(numeric_columns)
            ).run()
            outlier_params['specify_auto_drop_row_extr'] = selected_cols
        elif specify_col_choice[0] == 'auto':
            outlier_params['specify_auto_drop_row_extr'] = 'auto'
        else:
            outlier_params['specify_auto_drop_row_extr'] = None
#endregion 选择是否指定检测列
#region 设置异常值比例: contamination
        if outlier_choice in ['isolation_forest', 'multivariate']:
            contamination_options = ['0.01', '0.05', '0.1', '0.15', '0.2', '0.3']
            selected_cont = interactive(
                contamination_options,
                title="请选择异常值比例",
                description="异常值占总样本的比例估计",
                min_select=1, max_select=1
            ).run()
            outlier_params['contamination'] = float(selected_cont[0])
#endregion 
    # 生成结果并可视化
    result = {'outlier_preprocessing': outlier_params}
    visualize_route(result)
    return result

def outlier_py(data, auto_test=False):
    return analyze_outlier_distribution(data, auto_test=auto_test)

if __name__ == "__main__":
    import pandas as pd
    import numpy as np

    np.random.seed(42)
    data = pd.DataFrame({
        'feature1': np.random.normal(50, 10, 100),
        'feature2': np.random.normal(100, 20, 100),
        'feature3': np.random.normal(200, 30, 100),
        'label': ['A'] * 50 + ['B'] * 50
    })

    data.loc[0, 'feature1'] = 500
    data.loc[1, 'feature2'] = 800
    data.loc[2, 'feature3'] = 1200

    ColorPrinter.print_info("测试数据:")
    ColorPrinter.print_any(data.head(), color='white')

    ColorPrinter.print_info("\n测试异常值处理:")
    result = outlier_py(data)
    ColorPrinter.print_success("处理结果:")
    ColorPrinter.print_any(result, color='white')
