from statsmodels.regression.linear_model import RegressionResults

from src.analysis_functions.comparison_variance_in_and_between_group import (
    ComparisonVariance,
)
from src.analysis_functions.descriptive import DescriptiveAnalysis
from src.analysis_functions.regression import Regression
from src.analysis_functions.specific_analysis.increase_per_up_and_downvote import (
    InfluenceOfUpAndDownvotesOnReplies,
)
from src.analysis_functions.ttest import TTest
from src.analysis_functions.pearson_correlation import PearsonCorrelation

from src.analysis_functions.visualization import DataVisualizer
from src.analysis_wrappers.comparison_variance_in_and_between_group_wrapper import (
    run_comparison_variance_in_and_between_group,
)
from src.analysis_wrappers.descriptive_wrapper import run_descriptive_analysis

from src.analysis_wrappers.regression_wrapper import run_regression
from src.analysis_wrappers.pearson_correlation_wrapper import run_pearson_correlation
from src.analysis_wrappers.specific_analysis_wrappers.get_function_inverse_bayes_transformed_regression import (
    run_get_function_inverse_bayes_transformed_regression,
)
from src.analysis_wrappers.specific_analysis_wrappers.increase_per_up_and_downvote_wrapper import (
    run_report_influence_of_up_and_downvotes_on_replies,
)
from src.analysis_wrappers.ttest_wrapper import run_ttest
from src.analysis_wrappers.visualization_wrapper import run_visualization
from src.data_classes.parameters_analysis_comparison_variance_in_and_between_group import (
    ComparisonVarianceInAndBetweenGroupParameters,
)
from src.data_classes.parameters_analysis_get_function_inverse_bayes_transformed_regression import (
    GetFunctionInverseBayesTransformedRegressionParameters,
)
from src.data_classes.parameters_analysis_influence_of_up_and_downvotes import (
    InfluenceOfVotesParameters,
)

from src.data_classes.parameters_analysis_regression import (
    BayesianRegressionParameters,
    LinearRegressionParameters,
    GroupedLinearRegressionParameters,
)
from src.data_classes.parameters_analysis_pearson_correlation import (
    PearsonCorrelationParameters,
)
from src.data_classes.parameters_analysis_ttest import (
    TTestParameters,
    PairedTTestParameters,
)
from src.utils.helper_functions import FunctionData


def run_analyses(analyses: dict, preprocessed_datasets: dict) -> None:
    """
    Orchestrates the execution of various statistical analyses and visualizations based on a configuration file.

    This function initializes analysis and visualization classes, assigns preprocessed data to analyses,
    categorizes analyses by type, and sequentially executes them. It supports descriptive statistics,
    regression analyses, t-tests, Pearson correlation analyses, comparison of variance, influence of up and downvotes,
    and data visualization. The function ensures that the necessary data and results are passed between analyses
    and visualizations as required.

    Parameters
    ----------
    analyses : dict
        A dictionary containing configurations for different categories of analyses
        (descriptive, analysis, visualization) and their parameters.
    preprocessed_datasets : dict
        A dictionary mapping dataset names to their preprocessed forms. This data is used across various analyses.

    Raises
    ------
    ValueError
        If an unknown analysis type is encountered in the configuration.
    """
    regression: Regression = Regression()
    comparison_variance: ComparisonVariance = ComparisonVariance()
    pearson_correlation: PearsonCorrelation = PearsonCorrelation()
    ttest: TTest = TTest()
    influence_up_and_downvotes: InfluenceOfUpAndDownvotesOnReplies = InfluenceOfUpAndDownvotesOnReplies()

    descriptive: DescriptiveAnalysis = DescriptiveAnalysis()
    visualizer: DataVisualizer = DataVisualizer()

    for category in ["descriptive", "analysis", "visualization"]:
        if category in analyses:
            for analysis in analyses[category]:
                analysis.data = preprocessed_datasets[analysis.dataset]

    regression_analyses: list = []
    pearson_correlation_analyses: list = []
    ttest_analyses: list = []
    comparison_variance_in_and_between_group_analyses: list = []
    influence_up_and_downvotes_analyses: list = []
    get_function_inverse_bayes_transformed_regression_analyses: list = []

    if "descriptive" in analyses:
        run_descriptive_analysis(descriptive, analyses["descriptive"])

    for analysis in analyses.get("analysis", []):
        if isinstance(
            analysis,
            (
                LinearRegressionParameters,
                GroupedLinearRegressionParameters,
                BayesianRegressionParameters,
            ),
        ):
            regression_analyses.append(analysis)
        elif isinstance(analysis, ComparisonVarianceInAndBetweenGroupParameters):
            comparison_variance_in_and_between_group_analyses.append(analysis)
        elif isinstance(analysis, PearsonCorrelationParameters):
            pearson_correlation_analyses.append(analysis)
        elif isinstance(analysis, (TTestParameters, PairedTTestParameters)):
            ttest_analyses.append(analysis)
        elif isinstance(analysis, InfluenceOfVotesParameters):
            influence_up_and_downvotes_analyses.append(analysis)
        elif isinstance(
            analysis, GetFunctionInverseBayesTransformedRegressionParameters
        ):
            get_function_inverse_bayes_transformed_regression_analyses.append(analysis)
        else:
            raise ValueError(f"Unknown analysis type for analysis: {analysis}")

    regression_results: dict[str, RegressionResults] = {}
    if regression_analyses:
        regression_results: dict[str, RegressionResults] = run_regression(
            regression, regression_analyses
        )

    if comparison_variance_in_and_between_group_analyses:
        run_comparison_variance_in_and_between_group(
            comparison_variance, comparison_variance_in_and_between_group_analyses
        )

    if pearson_correlation_analyses:
        run_pearson_correlation(pearson_correlation, pearson_correlation_analyses)

    ttest_results: dict[str, tuple[float, float, float]] = {}
    if ttest_analyses:
        ttest_results: dict[str, tuple[float, float, float]] = run_ttest(
            ttest, ttest_analyses
        )

    if influence_up_and_downvotes_analyses:
        if regression_results == {}:
            raise ValueError(
                "Regression results are required for the influence of up and downvotes analysis"
            )
        run_report_influence_of_up_and_downvotes_on_replies(
            influence_up_and_downvotes,
            influence_up_and_downvotes_analyses,
            regression_results,
        )

    functions: dict[str, FunctionData] = {}
    if get_function_inverse_bayes_transformed_regression_analyses:
        functions: dict[
            str, FunctionData
        ] = run_get_function_inverse_bayes_transformed_regression(
            get_function_inverse_bayes_transformed_regression_analyses,
            regression_results,
        )

    if "visualization" in analyses:
        run_visualization(
            visualizer,
            analyses["visualization"],
            regression_results,
            functions,
            ttest_results,
        )
