#' Validate rxode2
#' This allows easy validation/qualification of nlmixr by running the
#' testing suite on your system.
#'
#' @param type Type of test or filter of test type, When this is an
#'   expression, evaluate the contents, respecting `skipOnCran`.  In
#'   the expression form, stray progress messages are muffled unless
#'   `options(rxode2.test.verbose = TRUE)` is set.
#' @param skipOnCran when `TRUE` skip the test on CRAN.
#' @author Matthew L. Fidler
#' @return nothing
#' @export
rxValidate <- function(type = NULL, skipOnCran=TRUE) {
  if (is(substitute(type), "{")) {
    if (isTRUE(skipOnCran)) {
      if (!identical(Sys.getenv("NOT_CRAN"), "true") ||
            !identical(Sys.getenv("rxTest"), "")) {
        return(invisible())
      }
    }
    if (!.Call(`_rxode2_isIntel`)) {
      rxUnloadAll()
    }
    # Preserve the rxode2 parallel/internal RNG seed across each test block.
    # A test that calls rxSetSeed(<n>) leaves useRxSeed=TRUE set globally;
    # without this guard that state leaks into later test files and breaks
    # set.seed()-based reproducibility tests (e.g. test-random, test-rxRmvn).
    .rxSeed0 <- rxGetSeed()
    on.exit(rxSetSeed(.rxSeed0), add = TRUE)
    if (getOption("rxode2.test.verbose", FALSE)) {
      return(force(type))
    }
    # Muffle stray progress messages (cli alerts, rxCat) during tests;
    # expect_message()/verify_output() handlers run innermost and still
    # see what they assert on.  The rxParseSuppressMsg()/.rxSilentErr
    # probe message(" ") must pass through, or muffling is mistaken for
    # suppressMessages() and sets the C-level silent flag, hiding
    # parse-error output some tests assert on.
    return(withCallingHandlers(
      force(type),
      message = function(m) {
        if (!identical(conditionMessage(m), " \n")) {
          tryInvokeRestart("muffleMessage")
        }
      }))
  }
  pt <- proc.time()
  .filter <- NULL
  if (is.null(type)) type <- FALSE
  if (is.character(type)) {
    .filter <- type
    type <- TRUE
  }
  if (type == TRUE) {
    .oldCran <- Sys.getenv("NOT_CRAN")
    .oldRxTest <- Sys.getenv("rxTest")
    Sys.setenv("NOT_CRAN" = "true") # nolint
    Sys.setenv("rxTest" = "") # nolint
    on.exit(Sys.setenv("NOT_CRAN" = .oldCran, "rxTest"=.oldRxTest)) # nolint
  } else if (type == FALSE) {
    .oldCran <- Sys.getenv("NOT_CRAN")
    .oldRxTest <- Sys.getenv("rxTest")
    Sys.setenv("NOT_CRAN" = "false") # nolint
    Sys.setenv("rxTest" = "false") # nolint
    on.exit(Sys.setenv("NOT_CRAN" = .oldCran, "rxTest"=.oldRxTest)) # nolint
  }
  .rxWithOptions(list(testthat.progress.max_fails = 10000000000), {
    path <- file.path(system.file("tests", package = "rxode2"), "testthat")
    .rxWithWd(path, {
      try(devtools::test(path, filter = .filter))
      message("=================================================================================")
      print(proc.time() - pt)
      message("=================================================================================")
    })
  })
}

#' @rdname rxValidate
#' @export
rxTest <- rxValidate
