from collections import namedtuple
from typing import NamedTuple

import pandas as pd
from statsmodels.regression.linear_model import RegressionResults

from src.utils.helper_functions import FunctionData


def get_function_inverse_bayes_transformed_regression(data: pd.DataFrame, model: RegressionResults) -> FunctionData:
    """
    Calculate and return a function representing the inverse Bayes transformed regression.

    This function constructs a parameter tuple for the regression function, and then returns
    a FunctionData object containing the regression
    function and its parameters.

    Parameters
    ---------
    data: pd.DataFrame
        The dataset containing the 'bayes-corrected (q=0.25) valence' column.
    model: RegressionResults
    The regression model results from which the gradient and intercept parameters are extracted.

    Returns
    -------
    FunctionData: An object containing the regression function and its parameters.
    """
    average_valence: float = data["bayes-corrected (q=0.25) valence"].mean()

    Param = namedtuple(
        "Param",
        [
            "average_valence",
            "gradient_valence",
            "gradient_totalvotes",
            "intercept",
        ],
    )

    def function(x: float, y: float, parameters: Param) -> float:
        return (
            parameters.gradient_valence
            * (-1 * (x / (x + y) + parameters.average_valence / (x + y)) - 0.5)
            + parameters.gradient_totalvotes * (x + y)
            + parameters.intercept
        )

    params: NamedTuple = Param(
        average_valence=average_valence,
        gradient_valence=model.params.iloc[1],
        gradient_totalvotes=model.params.iloc[2],
        intercept=model.params.iloc[0],
    )

    function_data: FunctionData = FunctionData(function, params)
    return function_data
