# ttest_calc.R — Datanovia t-test calculator engine (sourced by the lesson's {webr} calculator).
# Reusable, dependency-light: base `stats` + ggpubr only. One entry point, run_t_test(), covers
# one-sample, independent (Student/Welch) and paired designs. The calculator cell stays clean:
# paste data + options, then `source("ttest_calc.R"); run_t_test(...)`.

# Forgiving, locale-aware paste parser: accepts newline/space/comma/semicolon separators AND French
# decimal commas (38,9). One value per line is the documented, unambiguous path.
.dn_readnums <- function(s) {
  s <- trimws(s)
  if (grepl("\\.", s)) t <- strsplit(s, "[\n\t;, ]+")[[1]]
  else if (grepl("[0-9],[0-9]", s)) { t <- strsplit(s, "[\n\t; ]+")[[1]]; t <- gsub(",", ".", t, fixed = TRUE) }
  else t <- strsplit(s, "[\n\t;, ]+")[[1]]
  x <- suppressWarnings(as.numeric(t[nzchar(t)]))
  if (anyNA(x) || length(x) < 2) stop("Paste at least two numbers, one per line (e.g. from an Excel column).")
  x
}

.dn_d_label <- function(d) {
  as.character(cut(abs(d), c(-Inf, .2, .5, .8, Inf),
                   c("negligible", "small", "medium", "large"), right = FALSE))
}

.dn_report <- function(res, d) {
  print(res)
  cat(sprintf("Cohen's d = %.2f (%s effect)\n", d, .dn_d_label(d)))
}

# run_t_test(): the single calculator entry point.
#   group1        : pasted string of numbers (required)
#   group2        : pasted string (NULL = one-sample)
#   mu            : one-sample reference mean
#   alternative   : "two.sided" | "less" | "greater"
#   conf_level    : confidence level (0.95)
#   welch         : two-sample only — TRUE = Welch, FALSE = Student
#   paired        : TRUE = paired design (needs group1 & group2 of equal length)
run_t_test <- function(group1, group2 = NULL, mu = 0, alternative = "two.sided",
                       conf_level = 0.95, welch = TRUE, paired = FALSE) {
  library(ggpubr)
  x1 <- .dn_readnums(group1)

  if (is.null(group2)) {                                   # one-sample
    res <- t.test(x1, mu = mu, alternative = alternative, conf.level = conf_level)
    .dn_report(res, (mean(x1) - mu) / sd(x1))
    suppressWarnings(print(
      ggboxplot(data.frame(value = x1), y = "value", add = c("jitter", "mean"),
                fill = "#3a86d4", xlab = "", ylab = "Value") +
        ggplot2::geom_hline(yintercept = mu, linetype = "dashed", colour = "#8338ec")))
    return(invisible(res))
  }

  x2 <- .dn_readnums(group2)

  if (paired) {                                            # paired
    if (length(x1) != length(x2)) stop("Paired data needs the SAME number of values in both groups.")
    res <- t.test(x1, x2, paired = TRUE, alternative = alternative, conf.level = conf_level)
    .dn_report(res, mean(x1 - x2) / sd(x1 - x2))
    gg <- data.frame(id = rep(seq_along(x1), 2),
                     time = factor(rep(c("Before", "After"), each = length(x1)),
                                   levels = c("Before", "After")),
                     value = c(x1, x2))
    suppressWarnings(print(ggpaired(gg, x = "time", y = "value", color = "time",
                                    palette = c("#3a86d4", "#8338ec"), line.color = "gray70",
                                    xlab = "", ylab = "Value")))
    return(invisible(res))
  }

  # independent two-sample (Welch default)
  res <- t.test(x1, x2, alternative = alternative, conf.level = conf_level, var.equal = !welch)
  n1 <- length(x1); n2 <- length(x2)
  sp <- sqrt(((n1 - 1) * var(x1) + (n2 - 1) * var(x2)) / (n1 + n2 - 2))
  .dn_report(res, (mean(x1) - mean(x2)) / sp)
  gg <- data.frame(value = c(x1, x2),
                   group = factor(rep(c("Group 1", "Group 2"), c(n1, n2))))
  suppressWarnings(print(ggboxplot(gg, x = "group", y = "value", color = "group",
                                   palette = c("#3a86d4", "#8338ec"), add = c("jitter", "mean"),
                                   xlab = "", ylab = "Value")))
  invisible(res)
}
