new_ARCHmXAdditive <- function(eps, X, p, delta=2, covariates="all", 
                           method = "smooth_means_Positive_Constraint_Exp", ## one of  "smooth_means_Positive_Constraint_Exp", "smooth_means_lowes", "smooth_variance"
                           train_end = NULL, n_burn = 10, max_outer_iter = 30, tol = 1e-4,
                           hypothesisTest = TRUE, k.choice = "plugin")
{
  
  
  

  
  
  # Typing
  #X <- as.matrix(X)
  eps <- as.numeric(eps)
  p <- as.integer(p)
  N <- length(eps)
  
  if ((!identical(covariates,"all")) || (is.null(X))) 
  {
    if ((((covariates[1] == 0) || is.null(covariates))) || (is.null(X))) 
    {
      return(GARCHX(eps=eps, X = NULL, order = c(p,0), delta=delta))
    } else 
    {
      if (max(covariates) > ncol(X))
      {
        stop("Data matrix X incompatible with covariate list.")
      } 
      X <- X[, covariates, drop = FALSE]
    }
  } else { #covariates = "all" so change to a vector
    covariates <- 1:ncol(X)
  }
  
  if (!is.null(train_end)) {
    if (!is.numeric(train_end) || length(train_end) != 1){
      stop("train_end must be a single integer or NULL.")
    } 
    train_end <- as.integer(train_end)
    if (train_end <= p + n_burn){
      stop("train_end must be > p + n_burn.")
    } 
    if (train_end > N){
      stop("train_end must be <= length(eps).") 
    }
  }
  
  #method <- match.arg(method)
  #backfit.method <- switch(
  #  method,
  #  "A" = "smooth_means_Positive_Constraint_Exp",
  #  "B" = "smooth_means_lowes",
  #  "C" = "smooth_variance"
  #)
  
  # Fit model
  
  fit <- ARCHmXAdditive_estimate(
    eps = eps,
    X = X,
    p = p,
    delta = delta,
    train_end = train_end,
    n_burn = n_burn,
    max_outer_iter = max_outer_iter,
    tol = tol,
    backfit.method = method
  )
  

  # AIC, BIC
  AIC = -2 * fit$loglik + 2*p # TO DO: will find correct df
  BIC = -2 * fit$loglik + p*log(length(eps)) # TO DO: will find correct df 
  
  v_hat = eps^2 - fit$sigma_hat^2
  v_hat[!is.finite(v_hat) | is.na(v_hat)] = 0 
  residual_deviation <- sqrt(mean(v_hat^2)) 
  
  #################################################
  # Hypothesis testing for variable significance  
  #################################################
  
  alpha_p.values <- rep(NA_real_, p) # TBD!!
  covariate_p.values <- NULL
  p.values <- NULL
  
  if (hypothesisTest) {
    
    n_vars <- ncol(X)
    v_hats <- c()
    for (i in 1:n_vars) 
    {
      X_prime <- matrix(X[, -i], nrow=nrow(X))
      if (length(X_prime) > 0) {
        
        fit_prime <- new_ARCHmXAdditive(X = X_prime, p = p, eps = eps, delta = delta, covariates = "all",
                                    method = method, 
                                    train_end = train_end, n_burn = n_burn, max_outer_iter = max_outer_iter, tol = tol,
                                    hypothesisTest = FALSE, k.choice = k.choice
        ) # hypothesisTest = FALSE to prevent endless recursive loop
        
        v_hat_prime <- eps^2 - fit_prime$sigma_hat^2
        v_hat_prime[!is.finite(v_hat_prime) | is.na(v_hat_prime)] = 0 # must ensure not NA otherwise ARCHmX_anova_test_univariate won't work since Y might have nulls
        v_hats <- c(v_hats, v_hat_prime)
      }
      else {  # no covariates (we can just use ARCH_internal then)
        empty_model <- GARCHX(eps = eps, X=NULL, order = c(p,0), delta = delta)   # ARCH_internal(eps, p, delta = delta)
        v_hat_prime = empty_model$v_hat
        v_hat_prime[!is.finite(v_hat_prime) | is.na(v_hat_prime)] = 0 # must ensure not NA otherwise ARCHmX_anova_test_univariate won't work since Y might have nulls
        v_hats <- c(v_hats, v_hat_prime)
      }
    }
    
    # Now, let's perform the tests
    B <- 200
    alpha <- 0.05
    covariate_p.values <- rep(0, n_vars)
    
    next_odd <- function(n) {
      n <- floor(n)                 # floor each element
      ifelse(n %% 2 == 0, n + 1, n) # if even → next odd; if odd → keep
    }
    range <- unique(next_odd(seq(next_odd(N^(1/3)/2), next_odd(N^(1/3)), length = 5)))
    
    for (i in 1:n_vars){ # use the ARCHmX methods
      X_values <- X[,i][1:(N - 1)]
      offset <- N * (i-1)
      Y_values <- v_hats[(offset + 2):(offset + N)]
      if (k.choice == "plugin")
        k_n = next_odd(N^(29/90))
      else
        k_n <- ARCHmX_choosek(X_values, Y_values, range = range, B = B, alpha = alpha)
      
      covariate_p.values[i] <- ARCHmX_anova_test_univariate(X_values, Y_values, k_n) # relationship between removed variable and v_hat
    }
  }
  
  if (is.null(covariate_p.values)) {
    covariate_p.values <- numeric(0)
  }
  
  p.values <- c(alpha_p.values, covariate_p.values)
  

  #################################################
  # Set model parameters 
  #################################################
  
  structure(
    list(
      N = N,
      covariates = covariates, # vector of numbers indexing the covariates to be used
      method = method, # ## one of  "smooth_means_Positive_Constraint_Exp", "smooth_means_lowes", "smooth_variance"
      p = p, # order of ARCH
      X = X, # matrix of covariates
      eps = eps, 
      delta=delta,
      
      alphas = fit$alphas,
      m_funcs = fit$m_funcs, # list of callable functions
      m_hats = fit$m_hats,
      
      AIC = AIC, 
      BIC = BIC, 
      v_hat = v_hat,
      residual_deviation = residual_deviation, 
      
      sigma_hat = fit$sigma_hat,
      
      n_burn = fit$n_burn,
      
      log_QL = fit$loglik,
      converged = fit$converged,
      

      hypothesisTest = hypothesisTest, # variable-selection related 
      k.choice = k.choice,
      p.values = c(p.values), #this will become p_values for alphas not covariates
      covariate_p.values = c(covariate_p.values),
      
      train_end = train_end, # added 2/6/26
      max_outer_iter = max_outer_iter, 
      tol = tol
      ),
    class = "ARCHmXAdditive"
  )
}

