#' hatsurvey
#'
#' Computes survey indicator estimates using complex survey design
#' from the 'survey' package. It supports three types of estimation:
#' \itemize{
#'   \item \code{"mean"}: mean or simple proportion (svymean)
#'   \item \code{"prop"}: ratio-based proportion (svyratio, returned in percentage)
#'   \item \code{"ratio"}: ratio of two variables (e.g., GER, NER, LFPR)
#' }
#'
#' The output includes estimates, standard errors, relative standard errors, confidence intervals,
#' variance, design effect, and unweighted counts for numerator and denominator.
#'
#' @param x Character. Name of the target variable (numerator).
#' @param y Character. Name of the disaggregation (grouping) variable.
#' @param denom Character. Name of the denominator variable (only for \code{"prop"} and \code{"ratio"}).
#' @param design A survey design object created using \code{\link[survey]{svydesign}}.
#' @param denom_value A vector of values used to filter the denominator (optional).
#' @param success_value A vector of values considered as "success" in the numerator (optional).
#' @param data Original data frame used to preserve factor level ordering of \code{y}.
#' @param survey.type Character. Type of estimation:
#' \itemize{
#'   \item \code{"mean"}
#'   \item \code{"prop"}
#'   \item \code{"ratio"}
#' }
#'
#' @return A data frame containing:
#' \itemize{
#'   \item \code{Variable} : Name of the target variable
#'   \item \code{Disaggregation} : Disaggregation category
#'   \item \code{Estimation} : Estimated value
#'   \item \code{SE} : Standard error
#'   \item \code{RSE} : Relative standard error (%)
#'   \item \code{Lower Conf.Int} : Lower bound of confidence interval
#'   \item \code{Upper Conf.Int} : Upper bound of confidence interval
#'   \item \code{Variance} : Variance of the estimate
#'   \item \code{DEFF} : Design effect
#'   \item \code{n_denom} : Unweighted denominator count
#'   \item \code{n_num} : Unweighted numerator count (for prop and ratio)
#' }
#'
#' @details
#' \strong{Important notes:}
#' \itemize{
#'   \item For \code{"mean"}, the variable \code{x} should be numeric or binary (0/1).
#'   \item For \code{"prop"} and \code{"ratio"}, ensure that \code{x} and \code{denom}
#'   are properly defined (e.g., 1 = event, 0 = non-event).
#'   \item The function uses \code{svyby}, so results follow the complex survey design.
#'   \item Category ordering follows the factor levels in \code{data[[y]]}.
#'   \item For \code{"prop"}, the estimate is computed as a ratio of totals,
#'   not as a simple mean. This is useful for population-based indicators.
#' }
#' @examples
#' # --- Simple toydata
#' df <- data.frame(
#'   x = c(100, 0, 100, 100, 0, 100),
#'   denom = c(100, 100, 100, 100, 100, 100),
#'   y = factor(c("Urban","Urban","Rural","Rural","Urban","Rural")),
#'   w = c(2,1,3,1,2,1)
#' )
#'
#' # Build simple survey design
#' dsgn <- survey::svydesign(id = ~1, data = df, weights = ~w)
#'
#' # --- Proportion using proportion estimator
#' hatsurvey(
#'   x = "x",
#'   y = "y",
#'   denom = "denom",
#'   design = dsgn,
#'   denom_value = 100,
#'   success_value = 100,
#'   data = df,
#'   survey.type = "prop"
#' )
#'
#' # --- Full example (complex survey)
#' \donttest{
#' data("datause")
#'
#' # Prepare data
#' datause$R101 <- as.factor(datause$R101)
#' options(survey.lonely.psu = "certainty")
#' # Build complex survey design (3-stage, stratified, with FPC)
#' snlik.design <- survey::svydesign(
#'   id = ~IDSUBSLS + IDRUTA + IDIDV,
#'   strata = ~STRATA,
#'   data = subset(datause, !is.na(CR509)),
#'   weights = ~W_FINAL,
#'   fpc = ~FPC1 + FPC2 + FPC3,
#'   nest = TRUE
#' )
#'
#' # --- Proportion (percentage via ratio)
#' # Example: proportion of CR509 == 100 over total population
#' hatsurvey(
#'   x = "CR509",
#'   y = "R101",
#'   denom = "JMLH_PDDK",
#'   design = snlik.design,
#'   denom_value = NULL,
#'   success_value = 100,
#'   data = subset(datause, !is.na(CR509)),
#'   survey.type = "prop"
#' )
#'
#' # --- Ratio (e.g., conditional rate)
#' # Example: CR509 == 100 over CRCOB == 1
#' hatsurvey(
#'   x = "CR509",
#'   y = "R101",
#'   denom = "CRCOB",
#'   design = snlik.design,
#'   denom_value = 1,
#'   success_value = 100,
#'   data = subset(datause, !is.na(CR509)),
#'   survey.type = "ratio"
#' )
#'
#' # --- Mean
#' hatsurvey(
#'   x = "CR509",
#'   y = "R101",
#'   denom = NULL,
#'   design = snlik.design,
#'   denom_value = NULL,
#'   success_value = NULL,
#'   data = subset(datause, !is.na(CR509)),
#'   survey.type = "mean"
#' )
#' }
#'
#' @importFrom survey svyby svymean svyratio unwtd.count degf
#' @importFrom stats as.formula qt
#'
#' @export
hatsurvey = function(x, y, denom = NULL, design, denom_value = NULL, success_value = NULL, data, survey.type){
  if (!is.character(x) || !is.character(y)) {
    stop("x and y must be character variable names")
  } else{
    if (!y %in% names(data)) {
      stop("y must exist in data")
    } else {
  if (!survey.type %in% c("mean","prop","ratio")) {
    stop("survey.type must be 'mean', 'prop', or 'ratio'")
  } else{
    if (survey.type %in% c("prop", "ratio") && is.null(denom)) {
      stop("denom must be provided for 'prop' and 'ratio'")
    } else {
  if(survey.type=="ratio"){
    tabel <- survey::svyby(
      formula = stats::as.formula(paste0("~", x)),
      by = stats::as.formula(paste0("~", y)),
      design = design,
      FUN = survey::svyratio,
      denom = stats::as.formula(paste0("~", denom)),
      na.rm = TRUE,
      deff = TRUE,
      vartype = c("se", "ci", "cv", "cvpct", "var")
    )

    #tabel[is.na(tabel)] <- 0

    # --- Unweighted count denominator
    var_denom <- design$variables[[denom]]

    if (is.null(denom_value)) {
      design_den <- subset(design, !is.na(var_denom))
    } else {
      design_den <- subset(design, var_denom %in% denom_value)
    }

    n_denominator <- survey::svyby(
      formula = stats::as.formula(paste0("~", denom)),
      by = stats::as.formula(paste0("~", y)),
      design = design_den,
      FUN = survey::unwtd.count
    )

    names(n_denominator)[names(n_denominator) == "counts"] <- "n_denom"

    # --- Unweighted count numerator
    var_x <- design$variables[[x]]
    if (is.null(success_value)) {
      design_num <- subset(design, var_x > 0)
    } else {
      design_num <- subset(design, var_x %in% success_value)
    }

    n_numerator <- survey::svyby(
      formula = stats::as.formula(paste0("~", x)),
      by = stats::as.formula(paste0("~", y)),
      design = design_num,
      FUN = survey::unwtd.count
    )
    names(n_numerator)[names(n_numerator) == "counts"] <- "n_num"

    # --- Merge
    tabel <- merge(tabel, n_denominator, by = y, all.x = TRUE, sort = FALSE)
    tabel <- merge(tabel, n_numerator, by = y, all.x = TRUE, sort = FALSE)
    tabel[[y]] <- factor(tabel[[y]], levels = levels(data[[y]]))
    tabel <- tabel[order(tabel[[y]]), ]

    # --- Rename
    est_name <- paste0(x, "/", denom)
    se_name  <- paste0("se.", x, "/", denom)

    names(tabel)[names(tabel) == est_name] <- "estlab"
    names(tabel)[names(tabel) == se_name]  <- "selab"

    # --- CI
    tabel$theta     <- tabel$estlab
    tabel$SE        <- tabel$selab
    tabel$VAR       <- tabel$var
    tabel$CI_LOWER  <- tabel$estlab - stats::qt(0.975, df=survey::degf(design))*tabel$selab
    tabel$CI_UPPER  <- tabel$estlab + stats::qt(0.975, df=survey::degf(design))*tabel$selab
    tabel$RSE       <- tabel$`cv%`
    tabel$DEFF      <- tabel$DEff

    # --- Handle NA numerator
    tabel$n_num[is.na(tabel$n_num)] <- 0

    # --- Label
    tabel$Disaggr <- as.character(tabel[[y]])

    # --- Variable name
    tabel$Variable <- x

    # --- Select
    tabel <- tabel[, c(
      "Variable", "Disaggr", "theta", "SE", "RSE",
      "CI_LOWER", "CI_UPPER", "VAR", "DEFF",
      "n_denom", "n_num"
    )]

    names(tabel)[names(tabel) == "Disaggr"]  <- "Disaggregation"
    names(tabel)[names(tabel) == "theta"]    <- "Estimation"
    names(tabel)[names(tabel) == "CI_LOWER"] <- "Lower Conf.Int"
    names(tabel)[names(tabel) == "CI_UPPER"] <- "Upper Conf.Int"
    names(tabel)[names(tabel) == "VAR"] <- "Variance"

    return(tabel)

  }else{
    if(survey.type=="prop"){
      tabel <- survey::svyby(
        formula = stats::as.formula(paste0("~", x)),
        by = stats::as.formula(paste0("~", y)),
        design = design,
        FUN = survey::svyratio,
        denom = stats::as.formula(paste0("~", denom)),
        na.rm = TRUE,
        deff = TRUE,
        vartype = c("se", "ci", "cv", "cvpct", "var")
      )

      #tabel[is.na(tabel)] <- 0

      # --- Unweighted count denominator
      n_denominator <- survey::svyby(
        formula = stats::as.formula(paste0("~", x)),
        by = stats::as.formula(paste0("~", y)),
        design = design,
        FUN = survey::unwtd.count
      )
      names(n_denominator)[names(n_denominator) == "counts"] <- "n_denom"

      # --- Unweighted count numerator
      var_x <- design$variables[[x]]
      if (is.null(success_value)) {
        design_num <- subset(design, var_x > 0)
      } else {
        design_num <- subset(design, var_x %in% success_value)
      }

      n_numerator <- survey::svyby(
        formula = stats::as.formula(paste0("~", x)),
        by = stats::as.formula(paste0("~", y)),
        design = design_num,
        FUN = survey::unwtd.count
      )
      names(n_numerator)[names(n_numerator) == "counts"] <- "n_num"

      # --- Merge
      tabel <- merge(tabel, n_denominator, by = y, all.x = TRUE, sort = FALSE)
      tabel <- merge(tabel, n_numerator, by = y, all.x = TRUE, sort = FALSE)
      tabel[[y]] <- factor(tabel[[y]], levels = levels(data[[y]]))
      tabel <- tabel[order(tabel[[y]]), ]


      # --- Rename
      est_name <- paste0(x, "/", denom)
      se_name  <- paste0("se.", x, "/", denom)

      names(tabel)[names(tabel) == est_name] <- "estlab"
      names(tabel)[names(tabel) == se_name]  <- "selab"

      # --- CI
      tabel$theta     <- tabel$estlab*100
      tabel$SE        <- tabel$selab*100
      tabel$VAR       <- tabel$var*10000
      tabel$CI_LOWER  <- tabel$estlab*100 - stats::qt(0.975, df=survey::degf(design))*tabel$selab*100
      tabel$CI_UPPER  <- tabel$estlab*100 + stats::qt(0.975, df=survey::degf(design))*tabel$selab*100
      tabel$RSE       <- tabel$`cv%`
      tabel$DEFF      <- tabel$DEff

      # --- Handle NA numerator
      tabel$n_num[is.na(tabel$n_num)] <- 0

      # --- Label
      tabel$Disaggr <- as.character(tabel[[y]])

      # --- Variable name
      tabel$Variable <- x

      # --- Select
      tabel <- tabel[, c(
        "Variable", "Disaggr", "theta", "SE", "RSE",
        "CI_LOWER", "CI_UPPER", "VAR", "DEFF",
        "n_denom", "n_num"
      )]

      names(tabel)[names(tabel) == "Disaggr"]  <- "Disaggregation"
      names(tabel)[names(tabel) == "theta"]    <- "Estimation"
      names(tabel)[names(tabel) == "CI_LOWER"] <- "Lower Conf.Int"
      names(tabel)[names(tabel) == "CI_UPPER"] <- "Upper Conf.Int"
      names(tabel)[names(tabel) == "VAR"] <- "Variance"

      return(tabel)
    } else{if(survey.type=="mean"){
      # --- Estimate
      tabel <- survey::svyby(
        formula = stats::as.formula(paste0("~", x)),
        by = stats::as.formula(paste0("~", y)),
        design = design,
        FUN = survey::svymean,
        na.rm = TRUE,
        deff = TRUE,
        vartype = c("se", "ci", "cv", "cvpct", "var")
      )
      #tabel[is.na(tabel)] <- 0

      # --- Unweighted count denominator
      n_denominator <- survey::svyby(
        formula = stats::as.formula(paste0("~", x)),
        by = stats::as.formula(paste0("~", y)),
        design = design,
        FUN = survey::unwtd.count
      )
      names(n_denominator)[names(n_denominator) == "counts"] <- "n_denom"

      # --- Merge
      tabel <- merge(tabel, n_denominator, by = y, all.x = TRUE, sort = FALSE)
      tabel[[y]] <- factor(tabel[[y]], levels = levels(data[[y]]))
      tabel <- tabel[order(tabel[[y]]), ]


      # --- Rename
      col_est <- x
      col_se  <- grep("^se", names(tabel), value = TRUE)[1]

      names(tabel)[names(tabel) == col_est] <- "estlab"
      names(tabel)[names(tabel) == col_se]  <- "selab"

      # --- CI
      tabel$theta     <- tabel$estlab
      tabel$SE        <- tabel$selab
      tabel$VAR       <- tabel$var
      tabel$CI_LOWER  <- tabel$estlab - stats::qt(0.975, df=survey::degf(design))*tabel$selab
      tabel$CI_UPPER  <- tabel$estlab + stats::qt(0.975, df=survey::degf(design))*tabel$selab
      tabel$RSE       <- tabel$`cv%`
      tabel$DEFF      <- tabel$DEff

      # --- Label
      tabel$Disaggr <- as.character(tabel[[y]])

      # --- Variable name
      tabel$Variable <- x

      # --- Select
      tabel <- tabel[, c(
        "Variable", "Disaggr", "theta", "SE", "RSE",
        "CI_LOWER", "CI_UPPER", "VAR", "DEFF",
        "n_denom"
      )]

      names(tabel)[names(tabel) == "Disaggr"]  <- "Disaggregation"
      names(tabel)[names(tabel) == "theta"]    <- "Estimation"
      names(tabel)[names(tabel) == "CI_LOWER"] <- "Lower Conf.Int"
      names(tabel)[names(tabel) == "CI_UPPER"] <- "Upper Conf.Int"
      names(tabel)[names(tabel) == "VAR"] <- "Variance"

      return(tabel)
    }}}}}}}}
