#' Stochastic Approximation Confidence Interval for Correlation
#'
#' Computes confidence interval for the correlation of two populations
#' using stochastic approximation via resampling method (Garthwaite, 1996).
#'
#' @param x Numeric vector of first variable (must have same length as y)
#' @param y Numeric vector of second variable (must have same length as x)
#' @param conf.level Confidence level for the interval (default 0.95)
#'
#' @return An S3 object of class "corrCI_sa" containing:
#'   \item{lower}{Lower bound of the confidence interval}
#'   \item{upper}{Upper bound of the confidence interval}
#'   \item{estimate}{Point estimate of correlation coefficient}
#'   \item{conf.level}{The confidence level}
#'   \item{method}{Description of the method}
#'   \item{iterations}{List with components L (iterations for lower bound) and U (iterations for upper bound)}
#'
#' @details
#' This function implements the stochastic approximation algorithm for constructing
#' nonparametric confidence intervals for Pearson's correlation coefficient,
#' based on Garthwaite (1996). The algorithm uses recursive resampling to find
#' the quantiles of the sampling distribution.
#'
#' @references
#' Garthwaite, P. H. (1996). Confidence interval formation via stochastic approximation.
#' Statistics and Computing, 6(3), 235-241.
#'
#' @examples
#' set.seed(42)
#' x <- rnorm(30)
#' y <- x + rnorm(30, sd = 0.5)
#' result <- corrCI_sa(x, y)
#' print(result)
#'
#' @export
corrCI_sa <- function(x, y, conf.level = 0.95) {

  # Input validation
  if (!is.numeric(x) || !is.numeric(y)) {
    stop("x and y must be numeric vectors")
  }
  if (length(x) != length(y)) {
    stop("x and y must have the same length")
  }
  if (length(x) < 3) {
    stop("x and y must have at least 3 observations")
  }
  if (conf.level <= 0 || conf.level >= 1) {
    stop("conf.level must be between 0 and 1")
  }

  numObs <- length(x)

  # Original data
  x_orig <- x
  y_orig <- y

  # Standardization
  x <- (x_orig - mean(x_orig)) / sqrt(sum((x_orig - mean(x_orig))^2))
  y <- (y_orig - mean(y_orig)) / sqrt(sum((y_orig - mean(y_orig))^2))

  # Original estimate
  theta0 <- sum(x * y)

  # Obtain starting value for upper and lower limits
  numPerm <- 79
  transMatri <- y - theta0 * x
  delta <- c()
  for (i in 1:numPerm) {
    delta[i] <- sum(x[sample(seq(1, numObs, 1))] * transMatri)
  }
  startE <- diff(sort(delta)[c(2, numPerm - 1)]) / 2  # (t2-t1)/2
  U0 <- theta0 + startE
  L0 <- theta0 - startE
  m0 <- 50  # starting step

  # Stochastic approximation function
  saThetaQ <- function(x, y, q, thetaQ0, m0) {
    numMaxSimu <- 10000
    numForw <- 250
    numBack <- 250
    numStar <- 250
    eps <- (sd(x) + sd(y)) / 2 * 0.05

    zalpha <- qnorm(max(q, 1 - q))  # alpha quantile of standard normal distribution
    k <- 2 / (zalpha * ((2 * pi)^(-1 / 2)) * exp(-(zalpha^2) / 2))  # k value

    thetaQ <- c()
    istart <- m0

    # first steps
    thetaQ[istart] <- thetaQ0

    c <- k * abs(thetaQ[istart] - theta0)
    for (i in istart:(istart + numStar)) {
      transMatri_Perm <- y - thetaQ[i] * x
      mT <- sum(x[sample(numObs)] * transMatri_Perm)
      T0 <- sum(x * transMatri_Perm)
      thetaQ[i + 1] <- thetaQ[i] - c / (i - 1) * ((mT > T0) - q)  # recursive formula
      c <- k * abs(thetaQ[i + 1] - theta0)  # update constant
    }
    istart <- istart + numStar

    # continue search by every 250 steps before convergence
    while (sd(tail(thetaQ, numBack)) > eps & istart + numForw < numMaxSimu) {
      for (i in istart:(istart + numForw)) {
        transMatri_Perm <- y - thetaQ[i] * x
        mT <- sum(x[sample(numObs)] * transMatri_Perm)
        T0 <- sum(x * transMatri_Perm)
        thetaQ[i + 1] <- thetaQ[i] - c / (i - 1) * ((mT > T0) - q)  # recursive formula
        c <- k * abs(thetaQ[i + 1] - theta0)  # update constant
      }
      istart <- istart + numForw
    }
    return(thetaQ)
  }

  # Calculate alpha from conf.level
  alpha <- 1 - conf.level

  # Upper and lower limits
  L <- saThetaQ(x, y, alpha / 2, L0, m0)
  U <- saThetaQ(x, y, 1 - alpha / 2, U0, m0)

  # Build result object
  result <- list(
    lower = tail(L, 1),
    upper = tail(U, 1),
    estimate = theta0,
    conf.level = conf.level,
    method = "Stochastic Approximation Confidence Interval for Correlation (Garthwaite, 1996)",
    iterations = list(L = length(L) - m0, U = length(U) - m0)
  )

  class(result) <- "corrCI_sa"
  return(result)
}

#' Print Method for corrCI_sa Objects
#'
#' Prints the results of a correlation confidence interval analysis.
#'
#' @param x An object of class "corrCI_sa"
#' @param ... Additional arguments passed to print
#'
#' @return Prints the confidence interval, estimate, and method information.
#'
#' @method print corrCI_sa
#'
#' @export
print.corrCI_sa <- function(x, ...) {
  cat("\n")
  cat("  Stochastic Approximation CI for Correlation\n")
  cat("  ------------------------------------------------\n")
  cat(sprintf("  Estimate:   %.6f\n", x$estimate))
  cat(sprintf("  %g%% CI:    [ %.6f , %.6f ]\n",
              x$conf.level * 100, x$lower, x$upper))
  cat("  ------------------------------------------------\n")
  cat(sprintf("  Iterations: L = %d, U = %d\n", x$iterations$L, x$iterations$U))
  cat(sprintf("  Method:     %s\n", x$method))
  cat("\n")
  invisible(x)
}
