from dataclasses import dataclass
import numpy as np
import scipy.stats as stats

from cpistats.core.data_validation import to_numpy_1d


@dataclass
class OneSampleTTestResult:
    t_statistic: float
    p_value: float
    mean: float
    std_dev: float
    sample_size: int


def one_sample_t_test(data, mu0, alternative="two-sided"):
    """
    Perform a one-sample t-test.

    Parameters
    ----------
    data : array-like
        Sample observations.
    mu0 : float
        Hypothesized population mean.
    alternative : str
        "two-sided", "less", or "greater"

    Returns
    -------
    OneSampleTTestResult
    """

    x = to_numpy_1d(data)

    n = len(x)
    xbar = np.mean(x)
    s = np.std(x, ddof=1)
    se = s / np.sqrt(n)
    df = n - 1

    t_stat = (xbar - mu0) / se

    if alternative == "two-sided":
        p_value = 2 * (1 - stats.t.cdf(abs(t_stat), df=df))

    elif alternative == "greater":
        p_value = 1 - stats.t.cdf(t_stat, df=df)

    elif alternative == "less":
        p_value = stats.t.cdf(t_stat, df=df)

    else:
        raise ValueError("alternative must be 'two-sided', 'less', or 'greater'")

    return OneSampleTTestResult(
        t_statistic=t_stat,
        p_value=p_value,
        mean=xbar,
        std_dev=s,
        sample_size=n
    )