#' Generate Simulation Data for Interval-Censored Screening
#'
#' @description
#' Generates ultrahigh-dimensional simulation data for evaluating feature
#' screening methods under Case II interval censoring, following the
#' data-generating framework of the Log-rank SIS paper.
#' The true active predictor set is fixed at \eqn{\mathcal{D} = \{1,2,3,19,20\}}.
#'
#' Binary predictors are obtained by dichotomizing a latent Gaussian vector
#' with Toeplitz covariance \eqn{\Sigma_{jk} = \rho^{|j-k|}}.  The latent
#' response \eqn{Y^*} is generated from one of three models (linear, Poisson,
#' or Cox), and interval-censored observations \eqn{(Y^L_i, Y^U_i]} are
#' produced by adding asymmetric random noise to \eqn{Y^*_i}.
#'
#' @param n Number of subjects (rows of the design matrix).
#' @param p Number of predictors (columns of the design matrix).
#' @param rho AR(1) correlation between adjacent latent predictors.
#'   Must satisfy \eqn{0 \le \rho < 1}.
#' @param model Character string specifying the model for the latent response.
#'   One of \code{"linear"}, \code{"poisson"}, or \code{"cox"}.
#'   \describe{
#'     \item{\code{"linear"}}{Linear model \eqn{Y^* = \mathbf{x}^\top\boldsymbol\beta + \epsilon},
#'       \eqn{\epsilon \sim N(0,1)}.}
#'     \item{\code{"poisson"}}{Poisson regression with
#'       \eqn{\log\lambda = \mathbf{x}^\top\boldsymbol\beta},
#'       \eqn{\boldsymbol\beta = (1, 0.8, 0.6, \mathbf{0}_{15}^\top, -0.6, -0.8,
#'       \mathbf{0}_{p-20}^\top)^\top}.}
#'     \item{\code{"cox"}}{Cox proportional hazards with Weibull baseline
#'       (shape = 2, scale = 0.15) and
#'       \eqn{\boldsymbol\beta = (1.2, 1, 0.8, \mathbf{0}_{15}^\top, -1, -1.2,
#'       \mathbf{0}_{p-20}^\top)^\top}.}
#'   }
#' @param balanced Logical.  If \code{TRUE} (default), predictors are
#'   dichotomized at the median (\eqn{X_k = I(X^*_k > 0)}), yielding
#'   approximately equal group sizes.  If \code{FALSE}, the 70th percentile
#'   of \eqn{N(0,1)} is used as the threshold, producing imbalanced
#'   (sparse) binary predictors.
#' @param censoring Integer 1 or 2 selecting the censoring scenario:
#'   \describe{
#'     \item{\code{1}}{(default) \eqn{(p_I, p_R, p_L) = (80\%, 14\%, 6\%)}.}
#'     \item{\code{2}}{\eqn{(p_I, p_R, p_L) = (80\%, 6\%, 14\%)}.}
#'   }
#' @param seed Optional integer seed passed to \code{set.seed()} for
#'   reproducibility.  \code{NULL} (default) leaves the RNG state unchanged.
#'
#' @return A list with three elements:
#'   \describe{
#'     \item{\code{X}}{An \eqn{n \times p} binary integer matrix of predictors.}
#'     \item{\code{L}}{Numeric vector of length \eqn{n}: lower interval bounds.
#'       Left-censored observations have \code{L = -Inf}.}
#'     \item{\code{R}}{Numeric vector of length \eqn{n}: upper interval bounds.
#'       Right-censored observations have \code{R = Inf}.}
#'   }
#'
#' @references
#'
#' Fan, J. and Lv, J. (2008). Sure independence screening for ultrahigh
#' dimensional feature space.
#' \emph{Journal of the Royal Statistical Society: Series B},
#' \strong{70}(5), 849--911.
#'
#' Zhong, W., Qian, C., Liu, W., Zhu, L., and Li, R. (2023). Feature
#' screening for interval-valued response with application to study
#' association between posted salary and required skills.
#' \emph{Journal of the American Statistical Association},
#' \strong{118}, 805--817.
#'
#' @examples
#' ## Linear model, balanced predictors, censoring scenario 1
#' data <- GendataIC(n = 100, p = 500, rho = 0.5,
#'                   model = "linear", balanced = TRUE,
#'                   censoring = 1, seed = 2025)
#' X <- data$X; L <- data$L; R <- data$R
#' cat("Dimensions: n =", nrow(X), "  p =", ncol(X), "\n")
#' cat("Right-censored:", sum(is.infinite(R)), "\n")
#' cat("Left-censored: ", sum(is.infinite(L)), "\n")
#'
#' ## Poisson model, imbalanced predictors, censoring scenario 2
#' data2 <- GendataIC(n = 100, p = 500, rho = 0.2,
#'                    model = "poisson", balanced = FALSE,
#'                    censoring = 2, seed = 42)
#'
#' ## Cox model
#' data3 <- GendataIC(n = 100, p = 500, rho = 0.5,
#'                    model = "cox", balanced = TRUE, seed = 1)
#'
#' @importFrom MASS mvrnorm
#' @importFrom stats rpois rchisq rnorm qnorm runif rexp
#' @export
GendataIC <- function(n, p, rho,
                      model     = c("linear", "poisson", "cox"),
                      balanced  = TRUE,
                      censoring = 1L,
                      seed      = NULL) {

  model     <- match.arg(model)
  censoring <- as.integer(censoring)
  if (!censoring %in% 1:2)
    stop("'censoring' must be 1 or 2.")
  if (!is.null(seed)) set.seed(seed)

  ## ---- Active predictor set (fixed as in the paper) ----
  active_set <- c(1L, 2L, 3L, 19L, 20L)

  ## ---- Step 1: Latent continuous predictors ~ N(0, Sigma) ----
  sigma_vec <- rho^(0:(p - 1))
  Sigma     <- stats::toeplitz(sigma_vec)
  X_star    <- MASS::mvrnorm(n, mu = rep(0.0, p), Sigma = Sigma)

  ## ---- Step 2: Dichotomize to binary predictors ----
  threshold <- if (balanced) 0.0 else qnorm(0.7)
  X         <- (X_star > threshold) * 1L

  ## ---- Step 3: Generate latent response Y* ----
  a_n  <- 2.0 * log(n) / sqrt(n)   # signal magnitude (Fan & Lv 2008)

  Y_star <- switch(model,

    "linear" = {
      beta <- numeric(p)
      set_D <- c(1L, 2L, 3L)
      set_E <- c(19L, 20L)
      for (j in active_set) {
        Uj    <- if (j %in% set_D) 0L else 1L
        Zj    <- rnorm(1)
        beta[j] <- (-1)^Uj * (a_n + abs(Zj))
      }
      as.numeric(X %*% beta) + rnorm(n)
    },

    "poisson" = {
      beta <- numeric(p)
      beta[active_set] <- c(1.0, 0.8, 0.6, -0.6, -0.8)
      lambda <- exp(as.numeric(X %*% beta))
      rpois(n, lambda)
    },

    "cox" = {
      beta <- numeric(p)
      beta[active_set] <- c(1.2, 1.0, 0.8, -1.0, -1.2)
      ## Weibull baseline: shape = 2, scale = 0.15 => H0(t) = (t/0.15)^2
      lp  <- as.numeric(X %*% beta)
      U   <- runif(n)
      ## Inverse CDF: T = 0.15 * (-log(U) * exp(-lp))^(1/2)
      0.15 * (-log(U) * exp(-lp))^0.5
    }
  )

  ## ---- Step 4: Generate interval bounds (asymmetric noise) ----
  Ui  <- rpois(n, lambda = 2)          # lower noise
  Vi  <- rchisq(n, df = 2)            # upper noise
  L_i <- floor(Y_star - Ui)
  R_i <- floor(Y_star + 2.0 * Vi)

  ## ---- Step 5: Apply Case II censoring ----
  ## Censoring proportions: (p_I, p_R, p_L)
  if (censoring == 1L) {
    p_I <- 0.80; p_R <- 0.14; p_L <- 0.06
  } else {
    p_I <- 0.80; p_R <- 0.06; p_L <- 0.14
  }

  cens_type <- sample(c("I", "R", "L"), n, replace = TRUE,
                      prob = c(p_I, p_R, p_L))

  L_obs <- L_i
  R_obs <- R_i

  ## Right-censored: only lower bound observed
  idx_R        <- cens_type == "R"
  R_obs[idx_R] <- Inf

  ## Left-censored: only upper bound observed
  idx_L        <- cens_type == "L"
  L_obs[idx_L] <- -Inf

  list(X = X, L = L_obs, R = R_obs)
}
