#' Composite Hypothesis Procedure for Type-II Censored Samples
#'
#' Evaluates goodness-of-fit under unknown parameters using MLE estimation,
#' transformation to complete sample, normal residual standardization, and modified CvM/AD statistics.
#'
#' @param data Numeric vector of observed order statistics.
#' @param n Total sample size (n >= length(data)).
#' @param pdf Probability density function taking \code{(x, params)}.
#' @param cdf Cumulative distribution function taking \code{(x, params)}.
#' @param sf Survival function taking \code{(x, params)}. If \code{NULL}, computed as \code{1 - cdf(x, params)}.
#' @param params Named list/vector of starting parameter values for MLE.
#' @param censoring Type of censoring: \code{"right"} or \code{"left"}.
#' @param transform Transformation method: \code{"ms"} (Michael-Schucany) or \code{"malmquist"}.
#' @param optim_control Optional control list passed to \code{\link[stats]{optim}}.
#'
#' @return A list containing:
#' \item{stat_W2}{Modified Cramér-von Mises statistic (_mW2 or _lW2).}
#' \item{stat_A2}{Modified Anderson-Darling statistic (_mA2 or _lA2).}
#' \item{W2}{Raw Cramér-von Mises statistic on standardized residuals.}
#' \item{A2}{Raw Anderson-Darling statistic on standardized residuals.}
#' \item{theta_hat}{Estimated parameter values.}
#' \item{convergence}{Optimization convergence code.}
#' @export
#'
#' @examples
#' data_exp <- c(0.1, 0.2, 0.3, 0.4, 0.7, 1.0, 1.4)
#' stat_composite_mle(
#'   data = data_exp, n = 20,
#'   pdf = function(x, p) dexp(x, rate = p$rate),
#'   cdf = function(x, p) pexp(x, rate = p$rate),
#'   params = list(rate = 0.1),
#'   censoring = "right",
#'   transform = "malmquist"
#' )
stat_composite_mle <- function(data,
                               n,
                               pdf,
                               cdf,
                               sf = NULL,
                               params,
                               censoring = c("right", "left"),
                               transform = c("malmquist", "ms"),
                               optim_control = list()) {
  censoring <- match.arg(censoring)
  transform <- match.arg(transform)

  if (!is.numeric(data) || length(data) == 0) {
    stop("`data` must be a non-empty numeric vector.")
  }
  r <- length(data)
  if (!is.numeric(n) || length(n) != 1 || n < r) {
    stop("`n` must be an integer >= length(data).")
  }

  if (is.null(sf)) {
    sf <- function(x, p = NULL) 1 - eval_func(cdf, x, p)
  }

  # Step 1: Compute MLE
  fit <- fit_mle(data = data, n = n, pdf = pdf, cdf = cdf, sf = sf, params = params,
                 censoring = censoring, optim_control = optim_control)
  theta_hat <- fit$par

  # Step 2: Probability integral transform v_i = F(x_i; theta_hat)
  eps <- .Machine$double.eps^0.5
  v_i <- eval_func(cdf, data, theta_hat)
  v_i <- pmin(pmax(v_i, eps), 1 - eps)

  if (transform == "ms") {
    v_star <- transform_ms(v_i, n)
  } else {
    v_star <- transform_malmquist(v_i, n, censoring = censoring)$W
  }

  v_star <- pmin(pmax(v_star, eps), 1 - eps)

  # Step 3: Normal probit transformation y_i = qnorm(v*_i)
  y <- stats::qnorm(v_star)

  # Step 4: Standardize
  y_bar <- mean(y)
  s_y2 <- stats::var(y)

  if (is.na(s_y2) || s_y2 <= .Machine$double.eps) {
    stop("Sample variance of normal residuals is zero or undefined (s_y <= 0). Cannot standardize.")
  }

  s_y <- sqrt(s_y2)
  u_std <- stats::pnorm((y - y_bar) / s_y)
  u_std <- sort(pmin(pmax(u_std, eps), 1 - eps))

  # Step 5: Compute W² and A²
  i_seq <- 1:r
  W2 <- sum((u_std - (2 * i_seq - 1) / (2 * r))^2) + 1 / (12 * r)
  A2 <- -r - (1 / r) * sum((2 * i_seq - 1) * log(u_std) + (2 * r + 1 - 2 * i_seq) * log(1 - u_std))

  # Step 6: Modification factors
  mod_W2 <- W2 * (1 + 0.5 / r)
  mod_A2 <- A2 * (1 + 0.75 / r + 2.25 / (r^2))

  list(
    stat_W2 = mod_W2,
    stat_A2 = mod_A2,
    W2 = W2,
    A2 = A2,
    theta_hat = theta_hat,
    convergence = fit$convergence
  )
}
