#==========================================================
# Print DataAudit Report
#==========================================================

#' Print a DataAudit Report
#'
#' Prints a concise summary of a data audit produced by
#' \code{\link{audit_data}}.
#'
#' @param x An object of class \code{DataAuditReport}.
#' @param ... Additional arguments, currently unused.
#'
#' @return The input object \code{x}, invisibly.
#'
#' @export
print.DataAuditReport <- function(
    x,
    ...
) {

  #---------------------------------------------
  # Validate object
  #---------------------------------------------
  required_components <- c(
    "overview",
    "variables",
    "duplicates",
    "summary",
    "rules"
  )

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

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

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

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

  required_summary <- c(
    "Rows",
    "Variables",
    "VariablesWithIssues",
    "DuplicateRows",
    "TotalIssues",
    "RuleViolations",
    "OverallIssues"
  )

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

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

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

    stop(
      "Invalid variable summary in 'DataAuditReport'.",
      call. = FALSE
    )
  }

  if (!"Issue" %in% names(x$variables)) {

    stop(
      "Invalid variable summary in 'DataAuditReport'.",
      call. = FALSE
    )
  }

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

    stop(
      "Invalid duplicate summary in 'DataAuditReport'.",
      call. = FALSE
    )
  }

  if (!"Duplicate" %in% names(x$duplicates)) {

    stop(
      "Invalid duplicate summary in 'DataAuditReport'.",
      call. = FALSE
    )
  }

  #---------------------------------------------
  # Extract summary
  #---------------------------------------------
  s <- x$summary[1L, ]

  #---------------------------------------------
  # Header
  #---------------------------------------------
  cat(
    "DataAudit Report\n"
  )

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

  #---------------------------------------------
  # Dataset summary
  #---------------------------------------------
  cat(
    sprintf(
      "Rows:                  %s\n",
      s$Rows
    )
  )

  cat(
    sprintf(
      "Variables:             %s\n",
      s$Variables
    )
  )

  cat(
    sprintf(
      "Variables with issues: %s\n",
      s$VariablesWithIssues
    )
  )

  cat(
    sprintf(
      "Duplicated rows:       %s\n",
      s$DuplicateRows
    )
  )

  cat(
    sprintf(
      "Total issues:          %s\n",
      s$TotalIssues
    )
  )

  cat(
    sprintf(
      "Rule violations:       %s\n",
      s$RuleViolations
    )
  )

  cat(
    sprintf(
      "Overall issues:        %s\n",
      s$OverallIssues
    )
  )

  #---------------------------------------------
  # Variables with issues
  #---------------------------------------------
  issue_variables <-
    x$variables[
      x$variables$Issue,
      ,
      drop = FALSE
    ]

  if (nrow(issue_variables) > 0L) {

    cat(
      "\nVariables with issues\n"
    )

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

    print(
      issue_variables,
      row.names = FALSE
    )

  } else {

    cat(
      "\nNo variable-level issues detected.\n"
    )
  }

  #---------------------------------------------
  # Duplicate rows
  #---------------------------------------------
  duplicate_rows <-
    x$duplicates[
      x$duplicates$Duplicate,
      ,
      drop = FALSE
    ]

  if (nrow(duplicate_rows) > 0L) {

    cat(
      "\nDuplicated rows\n"
    )

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

    print(
      duplicate_rows,
      row.names = FALSE
    )

  } else {

    cat(
      "\nNo duplicated rows detected.\n"
    )
  }

  #---------------------------------------------
  # Custom rule validation
  #---------------------------------------------
  if (!is.null(x$rules)) {

    if (
      !inherits(
        x$rules,
        "DataAuditRuleResult"
      )
    ) {

      stop(
        "Invalid rule results in 'DataAuditReport'.",
        call. = FALSE
      )
    }

    cat(
      "\nCustom rule validation\n"
    )

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

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

    cat(
      sprintf(
        "\nTotal rule violations: %s\n",
        x$rules$total_violations
      )
    )
  }

  invisible(x)
}
