
"""PKTron Algorithms Science — Statistical Sampling & Analysis."""
import numpy as np
_R = np.float32

def descriptive_stats(data):
    d = np.asarray(data, dtype=_R)
    return {"mean":float(d.mean()),"std":float(d.std()),
            "min":float(d.min()),"max":float(d.max()),
            "median":float(np.median(d)),
            "q25":float(np.percentile(d,25)),
            "q75":float(np.percentile(d,75)),
            "skewness":float(((d-d.mean())**3).mean()/max(d.std()**3,1e-30)),
            "kurtosis":float(((d-d.mean())**4).mean()/max(d.std()**4,1e-30))-3}

def bootstrap_ci(data, statistic_fn=None, n_bootstrap=2000,
                  confidence=0.95, seed=0):
    """Bootstrap confidence interval for statistic_fn applied to data."""
    rng = np.random.default_rng(seed)
    if statistic_fn is None: statistic_fn = np.mean
    d    = np.asarray(data, dtype=_R)
    boot = [float(statistic_fn(rng.choice(d, size=len(d), replace=True)))
            for _ in range(n_bootstrap)]
    boot = np.array(boot, dtype=_R)
    alpha= 1 - confidence
    lo   = float(np.percentile(boot, 100*alpha/2))
    hi   = float(np.percentile(boot, 100*(1-alpha/2)))
    return {"ci_low":lo,"ci_high":hi,"point_estimate":float(statistic_fn(d))}

def stratified_sample(data, strata, n_per_stratum, seed=0):
    """Stratified random sampling."""
    rng = np.random.default_rng(seed)
    data  = np.asarray(data)
    strata= np.asarray(strata)
    result= []
    for s in np.unique(strata):
        idx = np.where(strata==s)[0]
        k   = min(n_per_stratum, len(idx))
        chosen = rng.choice(idx, size=k, replace=False)
        result.append(data[chosen])
    return np.concatenate(result)

def kernel_density_estimate(data, x_eval, bandwidth=None):
    """Gaussian KDE. Returns density values at x_eval."""
    d = np.asarray(data, dtype=_R)
    x = np.asarray(x_eval, dtype=_R)
    if bandwidth is None:
        bandwidth = _R(1.06*d.std()*len(d)**(-0.2))
    density = np.zeros_like(x)
    for xi in d:
        density += np.exp(-0.5*((x-xi)/bandwidth)**2)
    density /= _R(len(d))*bandwidth*np.sqrt(2*_R(np.pi))
    return density

def chi_square_test(observed, expected):
    """Chi-square goodness-of-fit. Returns (chi2_stat, df, p_value)."""
    from scipy.stats import chi2
    obs = np.asarray(observed, dtype=_R)
    exp = np.asarray(expected, dtype=_R)
    chi2_stat = float(((obs-exp)**2/np.maximum(exp,_R(1e-10))).sum())
    df        = len(obs)-1
    p_value   = float(chi2.sf(chi2_stat, df))
    return {"chi2_stat":chi2_stat,"df":df,"p_value":p_value}
