#==========================================================
# Print DataAudit Rule Result
#==========================================================

#' Print a DataAudit Rule Result
#'
#' Prints a concise summary of custom audit-rule results
#' produced by \code{\link{apply_audit_rules}}.
#'
#' @param x An object of class \code{DataAuditRuleResult}.
#' @param ... Additional arguments, currently unused.
#'
#' @return The input object \code{x}, invisibly.
#'
#' @export
print.DataAuditRuleResult <- function(
    x,
    ...
) {

  #---------------------------------------------
  # Validate object
  #---------------------------------------------
  required_components <- c(
    "status",
    "total_violations",
    "summary",
    "range",
    "category",
    "unique",
    "required",
    "pattern"
  )

  if (
    !inherits(x, "DataAuditRuleResult") ||
    !all(required_components %in% names(x))
  ) {

    stop(
      "Invalid 'DataAuditRuleResult' object.",
      call. = FALSE
    )
  }

  #---------------------------------------------
  # Validate summary
  #---------------------------------------------
  if (!is.data.frame(x$summary)) {

    stop(
      "Invalid rule summary in 'DataAuditRuleResult'.",
      call. = FALSE
    )
  }

  required_summary <- c(
    "Rule",
    "Violations"
  )

  if (
    !all(
      required_summary %in%
      names(x$summary)
    )
  ) {

    stop(
      "Invalid rule summary in 'DataAuditRuleResult'.",
      call. = FALSE
    )
  }

  #---------------------------------------------
  # Header
  #---------------------------------------------
  cat(
    "DataAudit Rule Validation\n"
  )

  cat(
    "=========================\n\n"
  )

  #---------------------------------------------
  # Overall result
  #---------------------------------------------
  cat(
    sprintf(
      "Status:           %s\n",
      x$status
    )
  )

  cat(
    sprintf(
      "Total violations: %d\n",
      x$total_violations
    )
  )

  #---------------------------------------------
  # Rule summary
  #---------------------------------------------
  cat(
    "\nRule summary\n"
  )

  cat(
    "------------\n"
  )

  print(
    x$summary,
    row.names = FALSE
  )

  #---------------------------------------------
  # Variables with violations
  #---------------------------------------------
  result_groups <- list(
    Range = x$range,
    Category = x$category,
    Unique = x$unique,
    Required = x$required,
    Pattern = x$pattern
  )

  violation_variables <- character()

  for (rule_name in names(result_groups)) {

    group <- result_groups[[rule_name]]

    if (length(group) == 0L) {
      next
    }

    for (variable in names(group)) {

      z <- group[[variable]]

      if (
        is.data.frame(z) &&
        "Violation" %in% names(z) &&
        any(z$Violation)
      ) {

        violation_variables <- c(
          violation_variables,
          sprintf(
            "%s: %s",
            rule_name,
            variable
          )
        )
      }
    }
  }

  #---------------------------------------------
  # Print affected variables
  #---------------------------------------------
  if (length(violation_variables) > 0L) {

    cat(
      "\nVariables with rule violations\n"
    )

    cat(
      "------------------------------\n"
    )

    for (item in violation_variables) {

      cat(
        sprintf(
          "- %s\n",
          item
        )
      )
    }

  } else {

    cat(
      "\nNo rule violations detected.\n"
    )
  }

  invisible(x)
}
