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

from cpistats.core.data_validation import to_numpy_1d


@dataclass
class TwoSampleTTestResult:
    t_statistic: float
    p_value: float
    mean1: float
    mean2: float
    std1: float
    std2: float
    n1: int
    n2: int


def two_sample_t_test(
    data1,
    data2,
    delta0=0.0,
    alternative="two-sided",
    equal_var=False
):
    """
    Two-sample t-test.

    Parameters
    ----------
    data1, data2 : array-like
    delta0 : float
        Hypothesized difference (μ1 − μ2)
    alternative : str
        "two-sided", "less", or "greater"
    equal_var : bool
        True = pooled t-test
        False = Welch t-test (default)

    Returns
    -------
    TwoSampleTTestResult
    """

    x1 = to_numpy_1d(data1)
    x2 = to_numpy_1d(data2)

    n1, n2 = len(x1), len(x2)

    mean1 = np.mean(x1)
    mean2 = np.mean(x2)

    std1 = np.std(x1, ddof=1)
    std2 = np.std(x2, ddof=1)

    if equal_var:
        # Pooled
        sp2 = ((n1 - 1)*std1**2 + (n2 - 1)*std2**2) / (n1 + n2 - 2)
        sp = np.sqrt(sp2)
        se = sp * np.sqrt(1/n1 + 1/n2)
        df = n1 + n2 - 2
    else:
        # Welch
        se = np.sqrt(std1**2/n1 + std2**2/n2)
        num = (std1**2/n1 + std2**2/n2)**2
        den = (std1**2/n1)**2/(n1-1) + (std2**2/n2)**2/(n2-1)

        df_raw = num / den
        df = int(df_raw)  # TRUNCATE (Minitab behavior)

    t_stat = ((mean1 - mean2) - delta0) / se

    if alternative == "two-sided":
        p_value = 2 * (1 - stats.t.cdf(abs(t_stat), df))
    elif alternative == "greater":
        p_value = 1 - stats.t.cdf(t_stat, df)
    elif alternative == "less":
        p_value = stats.t.cdf(t_stat, df)
    else:
        raise ValueError("alternative must be 'two-sided', 'less', or 'greater'")

    return TwoSampleTTestResult(
        t_statistic=t_stat,
        p_value=p_value,
        mean1=mean1,
        mean2=mean2,
        std1=std1,
        std2=std2,
        n1=n1,
        n2=n2
    )
