#' Create a design-aware survey object
#'
#' @param data Survey microdata.
#' @param weights,strata,psu,area Column names supplied as strings.
#' @param replicate_weights Optional character vector naming replicate-weight
#'   columns.
#' @return An object of class `inter_design`.
#' @export
inter_design <- function(data, weights, area, strata = NULL, psu = NULL,
                         replicate_weights = NULL) {
  .inter_assert_data_frame(data, "data")
  weights <- .inter_assert_column(data, weights, "weights")
  area <- .inter_assert_column(data, area, "area")
  strata <- .inter_assert_column(data, strata, "strata", allow_null = TRUE)
  psu <- .inter_assert_column(data, psu, "psu", allow_null = TRUE)

  if (!is.null(replicate_weights)) {
    if (!is.character(replicate_weights) || !length(replicate_weights) ||
        !all(replicate_weights %in% names(data))) {
      stop("`replicate_weights` must name columns in `data`.", call. = FALSE)
    }
  }
  w <- data[[weights]]
  if (!is.numeric(w) || any(!is.finite(w)) || any(w < 0) || sum(w) <= 0) {
    stop("Survey weights must be finite, non-negative, and have a positive sum.",
         call. = FALSE)
  }
  if (anyNA(data[[area]])) {
    stop("The area variable may not contain missing values.", call. = FALSE)
  }

  structure(
    list(
      data = data,
      weights = weights,
      area = area,
      strata = strata,
      psu = psu,
      replicate_weights = replicate_weights
    ),
    class = "inter_design"
  )
}

#' @export
print.inter_design <- function(x, ...) {
  cat("Intersectional survey design\n")
  cat("  Records: ", nrow(x$data), "\n", sep = "")
  cat("  Area: ", x$area, "\n", sep = "")
  cat("  Weight: ", x$weights, "\n", sep = "")
  if (!is.null(x$strata)) cat("  Strata: ", x$strata, "\n", sep = "")
  if (!is.null(x$psu)) cat("  PSU: ", x$psu, "\n", sep = "")
  if (!is.null(x$replicate_weights)) {
    cat("  Replicate weights: ", length(x$replicate_weights), "\n", sep = "")
  }
  invisible(x)
}
