#' Design-based hypothesis test for the comparison of two independent AUCs.
#'
#' @param design.1 An object of class \code{survey.design} generated by
#' \code{survey::svydesign} indicating the complex sampling design of the data set 1.
#' @param response.var.1 A character string with the name of the column indicating the response variable in the data set 1.
#' @param phat.var.1 A character string with the name of the column indicating the estimated probabilities in the data set 1.
#' @param design.2 An object of class \code{survey.design} generated by
#' \code{survey::svydesign} indicating the complex sampling design of the data set 2.
#' @param response.var.2 A character string with the name of the column indicating the response variable in the data set 2.
#' @param phat.var.2 A character string with the name of the column indicating the estimated probabilities in the data set 2.
#' @param tag.event A character string indicating the label used to indicate the event of interest.
#' 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.
#' 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 var
#' @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{
#' des.1 <- survey::svydesign(ids = ~cluster, strata = ~strata, weights=~weights, 
#'                            data = example_variables_wroc, nest=TRUE)
#' m.1 <- survey::svyglm(y ~ x1 + x2 + x3 + x4 + x5 + x6, design = des.1, family = quasibinomial())
#' example_variables_wroc$phat.1 <- predict(m.1, newdata = example_variables_wroc, type = "response")
#' des.1 <- survey::svydesign(ids = ~cluster, strata = ~strata, weights = ~weights,
#'                            data = example_variables_wroc, nest=TRUE)
#' des.2 <- survey::svydesign(ids = ~cluster, strata = ~strata, weights=~weights, 
#'                            data = example_variables_wroc_2, nest=TRUE)
#' m.2 <- survey::svyglm(y ~ x1 + x2 + x3 + x4 + x5 + x6, design = des.2, family = quasibinomial())
#' example_variables_wroc$phat.2 <- predict(m.1, newdata = example_variables_wroc_2, type = "response")
#' des.2 <- survey::svydesign(ids = ~cluster, strata = ~strata, weights = ~weights,
#'                            data = example_variables_wroc_2, nest=TRUE)
#'                            
#' # JKn-based hypothesis test:
#' jkn.ht <- ht.indep(design.1=des.1, response.var.1="y", phat.var.1 = "phat.1",
#'                    design.2=des.2, response.var.2="y", phat.var.2 = "phat.2",
#'                    tag.event=1, tag.nonevent=0, method="JKn")
#'                    
#' # Bootstrap-based hypothesis test:
#' boot.ht <- ht.indep(design.1=des.1, response.var.1="y", phat.var.1 = "phat.1",
#'                     design.2=des.2, response.var.2="y", phat.var.2 = "phat.2",
#'                     tag.event=1, tag.nonevent=0, method="subbootstrap")
#' }
#'                     
ht.indep <- function(design.1, response.var.1, phat.var.1, 
                     design.2, response.var.2, phat.var.2, 
                     tag.event = NULL, tag.nonevent = NULL,
                     alternative = c("two.sided", "greater", "less"),
                     method = c("JKn","subbootstrap"), boot.B=1000){
  
  data.1 <- get(design.1$call$data)
  weights.1 <- as.character(design.1$call$weights[2])
  weights.var.1 <- data.1[,weights.1]
  
  data.2 <- get(design.2$call$data)
  weights.2 <- as.character(design.2$call$weights[2])
  weights.var.2 <- data.2[,weights.2]
  
  if(inherits(response.var.1, "character")){
    response.var.1 <- data.1[,response.var.1]
  }
  
  if(length(table(response.var.1))!=2){stop("Response variable must have two classes.")}
  
  if(inherits(phat.var.1, "character")){
    phat.var.1 <- data.1[,phat.var.1]
  }
  
  if(inherits(response.var.2, "character")){
    response.var.2 <- data.2[,response.var.2]
  }
  
  if(length(table(response.var.2))!=2){stop("Response variable must have two classes.")}
  
  if(inherits(phat.var.2, "character")){
    phat.var.2 <- data.2[,phat.var.2]
  }
  
  if(length(response.var.1) != length(phat.var.1) || length(response.var.1) != length(weights.var.1)){
    stop("Vectors indicating the responses, predicted probabilities and sampling weights must be the same length.")
  }
  
  if(length(response.var.2) != length(phat.var.2) || length(response.var.2) != length(weights.var.2)){
    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.1)[which.max(table(response.var.1))])
      tag.event <- names(table(response.var.1)[which.min(table(response.var.1))])
    } else {
      tags <- names(table(response.var.1))
      tag.other <- which(tags == tag.event)
      tag.nonevent <- tags[-tag.other]
    }
  } else {
    if(is.null(tag.event)){
      tags <- names(table(response.var.1))
      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.1, phat.var = phat.var.1, weights.var = weights.var.1, 
                 tag.event = tag.event, tag.nonevent = tag.nonevent)$AUCw[1]
  wauc.2 <- wauc(response.var = response.var.2, phat.var = phat.var.2, weights.var = weights.var.2, 
                 tag.event = tag.event, tag.nonevent = tag.nonevent)$AUCw[1]
  
  if(method == "JKn"){
    JKn.w.1 <- stats::weights(survey::as.svrepdesign(design = design.1, type = method),"analysis")
    JKn.aucw.1 <- as.vector(apply(
      JKn.w.1, 2,
      function(x) wauc(
        response.var = response.var.1,
        phat.var = phat.var.1,
        weights.var = x,
        tag.event = tag.event,
        tag.nonevent = tag.nonevent
      )$AUCw[1]
    ))
    strata_var.1 <- attr(design.1$strata, "names")
    psu_var.1 <- attr(design.1$cluster, "names")
    nclus.h.1 <- table(unique(design.1$variables[,c(strata_var.1, psu_var.1)])[[strata_var.1]])
    id.0.1 <- apply(JKn.w.1==0, 2, which)
    strata_ids.1 <- sapply(id.0.1, function(indexes) {
      unique(design.1$variables[indexes, strata_var.1])
    })
    ah.1 <- nclus.h.1[as.character(strata_ids.1)]
    JKn.var.1 <- sum(((ah.1-1)/ah.1)*((JKn.aucw.1-wauc.1)^2))
    
    JKn.w.2 <- stats::weights(survey::as.svrepdesign(design = design.2, type = method),"analysis")
    JKn.aucw.2 <- as.vector(apply(
      JKn.w.2, 2,
      function(x) wauc(
        response.var = response.var.2,
        phat.var = phat.var.2,
        weights.var = x,
        tag.event = tag.event,
        tag.nonevent = tag.nonevent
      )$AUCw[1]
    ))
    strata_var.2 <- attr(design.2$strata, "names")
    psu_var.2 <- attr(design.2$cluster, "names")
    nclus.h.2 <- table(unique(design.2$variables[,c(strata_var.2, psu_var.2)])[[strata_var.2]])
    id.0.2 <- apply(JKn.w.2==0, 2, which)
    strata_ids.2 <- sapply(id.0.2, function(indexes) {
      unique(design.2$variables[indexes, strata_var.2])
    })
    ah.2 <- nclus.h.2[as.character(strata_ids.2)]
    JKn.var.2 <- sum(((ah.2-1)/ah.2)*((JKn.aucw.2-wauc.2)^2))
    
    d.sd <- sqrt(JKn.var.1+JKn.var.2)
    z <- (wauc.1 - wauc.2)/d.sd
    
  } else {
    
    if(method == "subbootstrap"){
      RB.boot.w.1 <- stats::weights(survey::as.svrepdesign(design = design.1, type = method, replicates=boot.B),"analysis")
      RB.aucw.b.1 <- as.vector(apply(
        RB.boot.w.1, 2,
        function(x) wauc(
          response.var = response.var.1,
          phat.var = phat.var.1,
          weights.var = x,
          tag.event = tag.event,
          tag.nonevent = tag.nonevent
        )$AUCw[1]
      ))
      RB.boot.w.2 <- stats::weights(survey::as.svrepdesign(design = design.2, type = method, replicates=boot.B),"analysis")
      RB.aucw.b.2 <- as.vector(apply(
        RB.boot.w.2, 2,
        function(x) wauc(
          response.var = response.var.2,
          phat.var = phat.var.2,
          weights.var = x,
          tag.event = tag.event,
          tag.nonevent = tag.nonevent
        )$AUCw[1]
      ))
      
      v.var1.RB <- var(RB.aucw.b.1)
      v.var2.RB <- var(RB.aucw.b.2)
      
      d.sd <- sqrt(v.var1.RB+v.var2.RB)
      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(z), lower.tail = FALSE)
  } else {
    if (alternative == "greater") {
      pval <- pnorm(z, lower.tail = FALSE)
    } else {
      if (alternative == "less") {
        pval <- pnorm(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 = z,
              pvalue = pval)
  
}