#' @export
print.inter_sae <- function(x, ...) {
  cat("Joint margin-constrained intersectional estimates\n")
  cat("  Formula: ", paste(deparse(x$formula), collapse = " "), "\n", sep = "")
  cat("  Family: ", x$family_label, "\n", sep = "")
  cat("  Domains: ", paste(x$domain, collapse = " x "), "\n", sep = "")
  cat("  Latent population cells: ", nrow(x$population$grid), "\n", sep = "")
  cat("  Margin convergence: ", if (x$population$converged) "yes" else "no",
      " (max relative error ", format(x$population$error, digits = 3), ")\n",
      sep = "")
  print(utils::head(inter_estimates(x), 10L), row.names = FALSE)
  invisible(x)
}

#' @export
summary.inter_sae <- function(object, ...) {
  identification <- check_identifiability(object)
  structure(
    list(
      call = object$call,
      formula = object$formula,
      family = object$family_label,
      survey_records = nrow(object$design$data),
      domains = object$domain,
      latent_cells = nrow(object$population$grid),
      population_total = sum(object$population$grid$.population),
      converged = object$population$converged,
      iterations = object$population$iterations,
      margin_error = object$population$error,
      nullity = identification$nullity,
      estimates = inter_estimates(object)
    ),
    class = "summary_inter_sae"
  )
}

#' @export
print.summary_inter_sae <- function(x, ...) {
  cat("Summary of interSAE fit\n")
  cat("  Survey records: ", x$survey_records, "\n", sep = "")
  cat("  Population total: ", format(x$population_total, scientific = FALSE),
      "\n", sep = "")
  cat("  Latent cells: ", x$latent_cells, "\n", sep = "")
  cat("  Unidentified dimensions: ", x$nullity, "\n", sep = "")
  cat("  Reconstruction iterations: ", x$iterations, "\n", sep = "")
  cat("  Maximum relative margin error: ",
      format(x$margin_error, digits = 4), "\n", sep = "")
  print(x$estimates, row.names = FALSE)
  invisible(x)
}

#' Plot intersectional estimates
#'
#' @param x A fitted `inter_sae` object.
#' @param y Ignored.
#' @param compare_direct Show direct survey estimates when available.
#' @param ... Additional arguments passed to [graphics::dotchart()].
#' @return The plotted data, invisibly.
#' @export
plot.inter_sae <- function(x, y = NULL, compare_direct = TRUE, ...) {
  estimates <- x$estimates
  label <- apply(estimates[x$domain], 1L, paste, collapse = " | ")
  order_index <- order(estimates$estimate)
  values <- estimates$estimate[order_index]
  labels <- label[order_index]
  graphics::dotchart(values, labels = labels,
                     xlab = if (x$family_label == "binomial")
                       "Estimated proportion" else "Estimated mean",
                     pch = 19, color = "#1B6CA8", ...)
  if (isTRUE(compare_direct)) {
    direct <- estimates$direct[order_index]
    ok <- is.finite(direct)
    graphics::points(direct[ok], which(ok), pch = 1, col = "#B23A48")
    graphics::legend("bottomright", legend = c("interSAE", "Direct"),
                     pch = c(19, 1), col = c("#1B6CA8", "#B23A48"),
                     bty = "n")
  }
  invisible(estimates[order_index, , drop = FALSE])
}
