suppressMessages({library(shiny); library(LRErdd); library(ggplot2); library(cowplot); library(DT)})
appdir <- "/home/claude/LRErdd2/inst/shiny-examples/LRErdd"
source(file.path(appdir, "server.R"), local = TRUE)
ok <- function(lbl) cat(sprintf("[PASS] %s\n", lbl))
bad <- function(lbl, e) cat(sprintf("[FAIL] %s -> %s\n", lbl, conditionMessage(e)))

testServer(server, {
  tryCatch({ d <- inFile_ds(); stopifnot(nrow(d) == 15984); ok("1-Datos por defecto") },
           error = function(e) bad("1-Datos", e))

  session$setInputs(var_forcing7 = "S", cutvalue2 = 15000, onezero2 = "under0",
                    seedval = 27, var_covar2 = c("HSTech", "hsgrade"), go_bwsel2 = 1)
  tryCatch({ o <- output$descriptive1; ok("2-Summary (2 covariables)") },
           error = function(e) bad("2-Summary", e))

  # caso límite: UNA covariable (antes fallaba con apply sobre vector)
  session$setInputs(var_covar2 = c("hsgrade"), go_bwsel2 = 2)
  tryCatch({ o <- output$descriptive1; ok("2-Summary con 1 covariable (drop=FALSE)") },
           error = function(e) bad("2-Summary 1 covariable", e))

  session$setInputs(typerange = "perce", bins = 25, stepunit = 1, nsim = 10,
                    var_covar = c("HSTech", "hsgrade"), go_bwsel = 1)
  tryCatch({ o <- output$summary; o2 <- output$histogram; ok("3-Part A: p-valores + histograma") },
           error = function(e) bad("3-Part A", e))
  tryCatch({ stopifnot(inherits(rv_plots$histogram, "ggplot")); ok("3-Plot capturado para descarga PNG") },
           error = function(e) bad("3-captura plot", e))

  session$setInputs(var_covar7 = "sex", intchar = "binary", go2 = 1)
  tryCatch({ o <- output$plotprop; stopifnot(!is.null(rv_plots$plotprop)); ok("3-Part B + captura") },
           error = function(e) bad("3-Part B", e))

  # selectize devuelve VECTOR de strings
  session$setInputs(bandwidths9 = c("1000", "2000"), niter9 = 10,
                    var_covarCovar9 = c("HSTech", "hsgrade"), go9 = 1)
  tryCatch({ t9 <- taula9(); stopifnot(nrow(t9) == 2); ok("4-Summary bandwidth (input vectorial)") },
           error = function(e) bad("4-Summary bandwidth", e))

  session$setInputs(bandwidths = c("1000", "2000"), niter = 10, typemod = "binary",
                    var_covarY = "dropout", cin = "0.05",
                    select_effect = "Sharp FEP", go_sharp_fep = 1)
  tryCatch({ tt <- taula(); stopifnot(nrow(tt$df) == 2); ok("5-Sharp FEP") },
           error = function(e) bad("5-Sharp FEP", e))

  session$setInputs(select_effect = "Sharp Neyman", go_sharp_neyman = 1)
  tryCatch({ tt <- taula(); stopifnot(all(is.finite(unlist(tt[, 5:6])))); ok("5-Sharp Neyman: IC finitos") },
           error = function(e) bad("5-Sharp Neyman", e))

  # validación: alfa inválido debe dar mensaje claro, no error críptico
  session$setInputs(cin = "95", go_sharp_neyman = 2)
  r <- tryCatch({ taula(); "no-error" },
                error = function(e) if (inherits(e, "shiny.silent.error") || grepl("alpha level", conditionMessage(e))) "validate" else conditionMessage(e))
  if (r == "validate") ok("5-Validación de alfa fuera de (0,1)") else bad("5-Validación alfa", simpleError(paste("resultado:", r)))

  session$setInputs(cin = "0.05", select_effect = "Fuzzy Neyman", var_covarW_neyman = "W", go_fuzzy_neyman = 1)
  tryCatch({
    tt <- taula(); cace <- tt[tt$Estimand == "CACE", ]
    stopifnot(abs((cace[[6]] - cace[[5]]) - 2 * qnorm(0.975) * cace[[4]]) < 0.05)
    ok("5-Fuzzy Neyman: IC correctos")
  }, error = function(e) bad("5-Fuzzy Neyman", e))

  session$setInputs(select_effect = "Fuzzy FEP", var_covarW = "W", M2 = 3,
                    one2side = "twosided", go_fuzzy_fep = 1)
  tryCatch({ tt <- taula(); stopifnot(length(tt) == 3); o <- output$plotres
             stopifnot(inherits(rv_plots$plotres, "ggplot")); ok("5-Fuzzy FEP + plot capturado") },
           error = function(e) bad("5-Fuzzy FEP", e))

  # tabla de resultados renderizada como DT con formato
  tryCatch({ j <- output$tablemethod; stopifnot(grepl("Buttons", j)); ok("5-Tabla DT con exportación") },
           error = function(e) bad("5-Tabla DT", e))
})
