#' Prepare training set for causal inference
#'
#' @param df The input dataframe. The datatype is dataframe.
#' @param y_name  The name of the response variable. The datatype is character.
#' @param continuous_name The name of continuous predictors. The datatype is character.
#' @param categorical_name The name of categorical predictors. The datatype is character.
#' @param subjectID_name The name of subjectID. The datatype is character.
#' @noRd
#'
#' @returns A list of prepared training set.
Train_Data_Preparation <- function(df,
                                   y_name,
                                   continuous_name,
                                   categorical_name,
                                   subjectID_name) {

  # if df is a tibble, convert it as dataframe
  df <- as.data.frame(df)
  # define response variable
  Y <- as.numeric(df[,y_name])
  # define X_continuous
  X_continuous <- as.data.frame(df[continuous_name])
  # define X_categorical
  X_categorical <- as.data.frame(df[categorical_name])
  # define ni_vector
  ni_vector <- as.numeric(table(df[subjectID_name]))
  # define group_info
  group_info <- as.numeric(df[,subjectID_name])
  # define output
  output <- list(Y = Y,
                 X_continuous = X_continuous,
                 X_categorical = X_categorical,
                 ni_vector = ni_vector,
                 group_info = group_info)
  return(output)
}

generate_design_matrix <- function(X_continuous, X_categorical) {

  # 1. Check for NULL inputs
  if (is.null(X_continuous) || is.null(X_categorical)) {
    stop("Error: Neither X_continuous nor X_categorical can be NULL.")
  }

  # 2. Ensure inputs are data frames
  if (!is.data.frame(X_continuous) || !is.data.frame(X_categorical)) {
    stop("Error: Both X_continuous and X_categorical must be data frames.")
  }

  # 3. Combine into a single data frame
  X_combined <- cbind(X_continuous, X_categorical)

  # 4. Create the design matrix
  # "~ .^3" creates main effects, 2-way, and 3-way interactions.
  # "- 1" removes the intercept term.
  design_matrix <- model.matrix(~ .^3 - 1, data = X_combined)

  return(design_matrix)
}
