#' Design-based hypothesis test for the comparison of two paired AUCs.
#'
#' @param design An object of class \code{survey.design} generated by
#' \code{survey::svydesign} indicating the complex sampling design of the data.
#' @param response.var A character string with the name of the column indicating the response variable in the data set.
#' @param phat.var.1 A character string with the name of the column indicating the estimated probabilities obtained with model 1 in the data set.
#' @param phat.var.2 A character string with the name of the column indicating the estimated probabilities obtained with model 2 in the data set.
#' @param tag.event A character string indicating the label used to indicate the event of interest in \code{response.var}.
#' The default option is \code{tag.event = NULL}, which selects the class with the lowest number of units as event.
#' @param tag.nonevent A character string indicating the label used for non-event in \code{response.var}.
#' The default option is \code{tag.nonevent = NULL}, which selects the class with the greatest number of units as non-event.
#' @param alternative A character string specifying the alternative hypothesis: \code{'two.sided'}, \code{greater}, or \code{less}. 
#' Default is \code{alternative = 'two.sided'}.
#' @param method A character string indicating the method implemented to estimate the variance: 
#' \code{method = 'JKn'} or \code{method = 'subbootstrap'}. Default is \code{method = 'JKn'}.
#' @param boot.B A numeric value indicating the number of bootstrap resamples to be considered. Default is \code{boot.B=1000}. Only for \code{method = 'subbootstrap'}. 
#'
#' @returns The output object of this function is a list of 5 elements containing the following information:
#' - `wauc.1`: a numeric value indicating the weighted point estimate of the AUC for model 1.
#' - `wauc.2`: a numeric value indicating the weighted point estimate of the AUC for model 2.
#' - `sd`: a numeric value indicating the square root of the estimated variance.
#' - `z`: a numeric value indicating the value of the statistic.
#' - `pvalue`: a numeric value indicating the p-value of the test.
#' 
#' @importFrom stats pnorm
#' @importFrom stats sd
#' @importFrom stats weights
#' 
#' @references Iparragirre, A., Lumley, T., & Barrio, I. (2026). 
#' Design-Based Inference for the AUC with Complex Survey Data. 
#' arXiv, 2603.28320. 
#' (https://arxiv.org/abs/2603.28320)
#' 
#' @export
#'
#' @examples
#' \donttest{
#' mydesign <- survey::svydesign(ids = ~cluster, strata = ~strata, weights=~weights,
#' data = example_variables_wroc, nest=TRUE)
#' model.1 <- survey::svyglm(y ~ x1 + x2 + x3, design = mydesign, family = quasibinomial())
#' model.2 <- survey::svyglm(y ~ x4 + x5 + x6, design = mydesign, family = quasibinomial())
#' phat.1 <- predict(model.1, newdata = example_variables_wroc, type = "response")
#' phat.2 <- predict(model.2, newdata = example_variables_wroc, type = "response")
#' example_variables_wroc$phat.1 <- phat.1
#' example_variables_wroc$phat.2 <- phat.2
#' mydesign <- survey::svydesign(ids = ~cluster, strata = ~strata, weights = ~weights,
#' data = example_variables_wroc, nest=TRUE)
#' 
#' # JKn-based hypothesis test:
#' ht.JKn <- ht.paired(design=mydesign, response.var = "y", phat.var.1 = "phat.1",
#'                     phat.var.2 = "phat.2", tag.event = 1, tag.nonevent = 0, 
#'                     method="JKn")
#'                     
#' # Bootstrap-based hypothesis test:
#' set.seed(123)
#' ht.boot <- ht.paired(design=mydesign, response.var = "y", phat.var.1 = "phat.1",
#'                      phat.var.2 = "phat.2", tag.event = 1, tag.nonevent = 0, 
#'                      method="subbootstrap")
#' }
#' 
ht.paired <- function(design, response.var, phat.var.1, phat.var.2, 
                      tag.event = NULL, tag.nonevent = NULL,
                      alternative = c("two.sided", "greater", "less"),
                      method = c("JKn","subbootstrap"), boot.B=1000){
  
  data <- get(design$call$data)
  weights <- as.character(design$call$weights[2])
  weights.var <- data[,weights]
  
  if(inherits(response.var, "character")){
    response.var <- data[,response.var]
  }
  
  if(length(table(response.var))!=2){stop("Response variable must have two classes.")}
  
  if(inherits(phat.var.1, "character")){
    phat.var.1 <- data[,phat.var.1]
  }
  
  if(inherits(phat.var.2, "character")){
    phat.var.2 <- data[,phat.var.2]
  }
  
  if(length(response.var) != length(phat.var.1) || length(response.var) != length(phat.var.2) || length(response.var) != length(weights.var)){
    stop("Vectors indicating the responses, predicted probabilities and sampling weights must be the same length.")
  }
  
  # Missing tags:
  if(is.null(tag.nonevent)){
    if(is.null(tag.event)){
      tag.nonevent <- names(table(response.var)[which.max(table(response.var))])
      tag.event <- names(table(response.var)[which.min(table(response.var))])
    } else {
      tags <- names(table(response.var))
      tag.other <- which(tags == tag.event)
      tag.nonevent <- tags[-tag.other]
    }
  } else {
    if(is.null(tag.event)){
      tags <- names(table(response.var))
      tag.other <- which(tags == tag.nonevent)
      tag.event <- tags[-tag.other]
    }
  }
  
  method <- match.arg(method)
  alternative <- match.arg(alternative)
  
  # Point estimates:
  wauc.1 <- wauc(response.var = response.var, phat.var = phat.var.1, weights.var = weights.var, 
                 tag.event = tag.event, tag.nonevent = tag.nonevent)$AUCw[1]
  wauc.2 <- wauc(response.var = response.var, phat.var = phat.var.2, weights.var = weights.var, 
                 tag.event = tag.event, tag.nonevent = tag.nonevent)$AUCw[1]
 
  if(method == "JKn"){
    JKn.w <- stats::weights(survey::as.svrepdesign(design = design, type = method),"analysis")
    JKn.aucw.1 <- as.vector(apply(
      JKn.w, 2,
      function(x) wauc(
        response.var = response.var,
        phat.var = phat.var.1,
        weights.var = x,
        tag.event = tag.event,
        tag.nonevent = tag.nonevent
      )$AUCw[1]
    ))
    JKn.aucw.2 <- as.vector(apply(
      JKn.w, 2,
      function(x) wauc(
        response.var = response.var,
        phat.var = phat.var.2,
        weights.var = x,
        tag.event = tag.event,
        tag.nonevent = tag.nonevent
      )$AUCw[1]
    ))
    
    d.aucs <- wauc.1-wauc.2
    jkn.d.aucs <- JKn.aucw.1-JKn.aucw.2
    
    strata_var <- attr(design$strata, "names")
    psu_var    <- attr(design$cluster, "names")
    
    nclus.h <- table(unique(design$variables[,c(strata_var, psu_var)])[[strata_var]])
    id.0 <- apply(JKn.w==0, 2, which)
    strata_ids <- sapply(id.0, function(indexes) {
      unique(design$variables[indexes, strata_var])
    })
    ah <- nclus.h[as.character(strata_ids)]
    
    JKn.var <- sum(((ah-1)/ah)*((jkn.d.aucs-d.aucs)^2))
    d.sd <- sqrt(JKn.var)
    d.z <- d.aucs/d.sd

  } else {
    
    if(method == "subbootstrap"){
      RB.boot.w <- stats::weights(survey::as.svrepdesign(design = design, type = method, replicates=boot.B),"analysis")
      RB.aucw.b.1 <- as.vector(apply(
        RB.boot.w, 2,
        function(x) wauc(
          response.var = response.var,
          phat.var = phat.var.1,
          weights.var = x,
          tag.event = tag.event,
          tag.nonevent = tag.nonevent
        )$AUCw[1]
      ))
      RB.aucw.b.2 <- as.vector(apply(
        RB.boot.w, 2,
        function(x) wauc(
          response.var = response.var,
          phat.var = phat.var.2,
          weights.var = x,
          tag.event = tag.event,
          tag.nonevent = tag.nonevent
        )$AUCw[1]
      ))
      
      RB.aucw.Db <- RB.aucw.b.1-RB.aucw.b.2
      d.sd <- sd(RB.aucw.Db)
      d.z <- (wauc.1-wauc.2)/d.sd

    } else {
      stop("One of the following methods must be selected: method = 'JKn' or method = 'subbootstrap'.")
    }
    
  }
  
  if (alternative == "two.sided") {
    pval <- 2*pnorm(abs(d.z), lower.tail = FALSE)
  } else {
    if (alternative == "greater") {
      pval <- pnorm(d.z, lower.tail = FALSE)
    } else {
      if (alternative == "less") {
        pval <- pnorm(d.z, lower.tail = TRUE)
      } else {
        stop("One of the following options must be selected for the alternative hypothesis: 'two.sided', 'greater' or 'less'")
      }
    } 
  }  
  
  obj <- list(wauc.1 = wauc.1,
              wauc.2 = wauc.2,
              sd = d.sd,
              z = d.z,
              pvalue = pval)
  
  return(obj)
  
}