#' DP-Quantile Bootstrap for Time Series
#'
#' Generate bootstrap time series using a Dirichlet-based quantile bootstrap
#' with rank-preserving reconstruction.
#'
#' @param x Numeric vector. Original time series.
#' @param R Integer. Number of bootstrap replications.
#' @param alpha Positive numeric. Dirichlet concentration parameter.
#' @param seed Optional seed.
#'
#' @return A list containing bootstrap samples, mean series, quantiles and ranks.
#'
#' @examples
#' x <- c(120, 125, 118, 130, 128, 135, 140, 138, 145, 150)
#' res <- dpq_bootstrap(x, R = 20, alpha = 1, seed = 123)
#' res$mean_series
#' dim(res$samples)
#'
#' @export
dpq_bootstrap <- function(x, R = 500, alpha = 1, seed = NULL) {

  if (!is.null(seed)) {
    set.seed(seed)
  }

  if (!is.numeric(x)) {
    stop('x must be a numeric vector.')
  }

  if (any(is.na(x))) {
    stop('x must not contain missing values.')
  }

  n <- length(x)

  if (n < 3) {
    stop('The series must contain at least 3 observations.')
  }

  if (R < 1) {
    stop('R must be greater than or equal to 1.')
  }

  if (alpha <= 0) {
    stop('alpha must be strictly positive.')
  }

  x_ordered <- sort(x)

  ranks <- rank(x, ties.method = 'first')

  z <- numeric(n + 1)

  z[1] <- x_ordered[1] - (x_ordered[2] - x_ordered[1]) / 2

  for (i in 2:n) {
    z[i] <- (x_ordered[i - 1] + x_ordered[i]) / 2
  }

  z[n + 1] <- x_ordered[n] + (x_ordered[n] - x_ordered[n - 1]) / 2

  u_low <- pmax(0.001, ((1:n) - 0.75) / (n + 0.5))

  u_high <- pmin(0.999, ((1:n) - 0.25) / (n + 0.5))

  X_boot <- matrix(NA_real_, nrow = R, ncol = n)

  rdirichlet1 <- function(alpha_vec) {
    g <- stats::rgamma(length(alpha_vec), shape = alpha_vec, rate = 1)
    g / sum(g)
  }

  for (b in 1:R) {

    w <- rdirichlet1(rep(alpha, n))

    F_cum <- cumsum(w)

    F_prev <- c(0, F_cum[-n])

    x_star_ordered <- numeric(n)

    for (i in 1:n) {

      u <- stats::runif(1, u_low[i], u_high[i])

      k <- which(F_cum >= u)[1]

      if (is.na(k)) {
        k <- n
      }

      denom <- F_cum[k] - F_prev[k]

      if (denom <= 0) {
        a <- 0
      } else {
        a <- (u - F_prev[k]) / denom
      }

      x_star_ordered[i] <- z[k] + a * (z[k + 1] - z[k])
    }

    X_boot[b, ] <- x_star_ordered[ranks]
  }

  boot_mean <- colMeans(X_boot)

  q25 <- apply(X_boot, 2, stats::quantile, probs = 0.25)
  q75 <- apply(X_boot, 2, stats::quantile, probs = 0.75)

  q025 <- apply(X_boot, 2, stats::quantile, probs = 0.025)
  q975 <- apply(X_boot, 2, stats::quantile, probs = 0.975)

  result <- list(
    original = x,
    ordered = x_ordered,
    ranks = ranks,
    z = z,
    samples = X_boot,
    mean_series = boot_mean,
    q25 = q25,
    q75 = q75,
    q025 = q025,
    q975 = q975,
    R = R,
    alpha = alpha
  )

  class(result) <- 'dpq_bootstrap'

  return(result)
}
