#' Fit Regression Model with One or More Predictors (Internal)
#'
#' Fits a regression model based on the selected approach. Can handle a single exposure or a vector of exposures.
#'
#' @param data A `data.frame` with complete observations for outcome and exposures.
#' @param outcome A string. Name of the outcome variable.
#' @param exposures A string or character vector of predictor(s).
#' @param approach A string specifying the regression approach. One of
#' `"logit"`, `"firth"`, `"logbinomial"`, `"poisson"`, `"linear"`, `"robpoisson"`, or `"negbin"`.
#'
#' @return A fitted model object (`glm`, `logistf`, `lm`, `riskratio`, or `negbin`) or `NULL` if fitting fails.
#' @keywords internal
.fit_uni_model <- function(data, outcome, exposures, approach) {
  approach <- .normalize_approach(approach)
  formula <- as.formula(paste(outcome, "~", exposures))

  tryCatch({
    # Fit model by approach
    fit <- switch(approach,
                  "logit" = glm(formula,
                                data = data,
                                family = binomial("logit")),
                  "firth" = logistf::logistf(formula = formula,
                                             data = data),
                  "logbinomial" = glm(formula,
                                       data = data,
                                       family = binomial("log")),
                  "poisson" = glm(formula,
                                  data = data,
                                  family = poisson("log")),
                  "linear" = lm(formula,
                                data = data),
                  "robpoisson" = risks::riskratio(formula,
                                                  data = data,
                                                  approach = "robpoisson"),
                  "negbin" = MASS::glm.nb(formula,
                                          data = data,
                                          control = glm.control(maxit = 200)),
                  stop(
                    paste0("Invalid approach: '", approach,
                           "'. Choose from: logit, firth, logbinomial, poisson, ",
                           "robpoisson, linear, negbin."),
                    call. = FALSE
                  )
    )
    attr(fit, "gtregression_model_frame") <- stats::model.frame(formula, data = data)
    return(fit)
  }, error = function(e) {
    warning("Model failed for exposure(s) '", paste(exposures, collapse = ", "),
            "' using '", approach, "': ", e$message, call. = FALSE)
    return(NULL)
  })
}
