This type of question is similar to the coupon collector's problem. You can find many similar types of questions and approaches on this website and online, but once you start making adjustments it becomes very difficult to find exact analytic expressions for the result. The selection of very rare or super rare cards makes this question fairly difficult, for example.
Instead, it's easier to use a computer to simulate the situation many times and find approximate probabilities from that. You can find many examples of this sort of simulation online as well. For example, here's a simulation in R of drawing a box and calculating the number of unique cards in it. I repeat the simulation 1000 times and plot a histogram of the number of unique cards.
# number of cards in each set
num_common <- 159
num_item <- 13
num_rare <- 79
num_vrare <- 31
num_srare <- 6
num_special <- num_common
make card names to sample from
commons <-
vapply(1:num_common, FUN = function(x)
paste0("C", formatC(x, width = 3, format = "d", flag = 0)), "A")
items <-
vapply(1:num_item, FUN = function(x)
paste0("I", formatC(x, width = 2, format = "d", flag = 0)), "A")
rares <-
vapply(1:num_rare, FUN = function(x)
paste0("R", formatC(x, width = 2, format = "d", flag = 0)), "A")
vrares <-
vapply(1:num_vrare, FUN = function(x)
paste0("VR", formatC(x, width = 2, format = "d", flag = 0)), "A")
srares <- vapply(1:num_srare, FUN = function(x) paste0("SR", x), "A")
specials <-
vapply(1:num_special, FUN = function(x)
paste0("SP", formatC(x, width = 3, format = "d", flag = 0)), "A")
functions to generate a random pack and random box
generate_pack <- function() {
common <- sample(commons, 11, replace = TRUE)
item <- sample(items, 1)
rare <- sample(rares, 1)
rare_draw <- sample(1:96,1) # randomly select type of other rare card
if(rare_draw == 96) {
other_rare <- sample(srares, 1)
} else if(rare_draw >= 88) {
other_rare <- sample(vrares, 1)
} else {
other_rare <- sample(rares, 1)
}
special <- sample(specials, 1)
return(c(common, item, rare, other_rare, special))
}
generate_box <- function() {
allcards <- c()
for(i in 1:16) {
allcards <- c(allcards, generate_pack())
}
return(allcards)
}
simulate 1000 times and plot histogram.
set.seed(1111) # for reproducibility
num_sims <- 1000
unique_cards <- rep(0, num_sims)
for(i in 1:num_sims) {
unique_cards[[i]] <- length(unique(generate_box()))
}
summary(unique_cards)
#> Min. 1st Qu. Median Mean 3rd Qu. Max.
#> 144.0 155.0 158.0 158.3 161.0 172.0
hist(unique_cards)

Created on 2022-07-13 by the reprex package (v2.0.1)
From this we can see that the odds of getting fewer than 100 unique cards is essentially 0. Out of 1000 simulations the fewest unique cards we saw was 144.
You can try running it online if you don't have R installed, and you can make various adjustments to see how the number of cards change. (This code could be simplified, for example by removing formatting from the card names, but I like it this way. If you want to sort and print the simulated cards from each box or pack it's relatively easy to do that as well.)