#==========================================================
# Summary DataAudit Rule Result
#==========================================================

#' Summarize a DataAudit Rule Result
#'
#' Produces a compact summary of custom validation-rule
#' results generated by \code{\link{apply_audit_rules}}.
#'
#' @param object An object of class
#'   \code{DataAuditRuleResult}.
#' @param ... Additional arguments, currently unused.
#'
#' @return An object of class
#'   \code{summary.DataAuditRuleResult}.
#'
#' @export

summary.DataAuditRuleResult <- function(
    object,
    ...
) {

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

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

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

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

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

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

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

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

  #---------------------------------------------
  # Helper: collect violation rows
  #---------------------------------------------
  collect_violations <- function(
    group,
    rule_name
  ) {

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

      return(
        data.frame(
          Rule = character(),
          Variable = character(),
          Row = integer(),
          Value = character(),
          stringsAsFactors = FALSE
        )
      )
    }

    pieces <- list()

    for (variable in names(group)) {

      x <- group[[variable]]

      if (
        !is.data.frame(x) ||
        !"Violation" %in% names(x)
      ) {
        next
      }

      bad <- which(
        !is.na(x$Violation) &
          x$Violation
      )

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

      value <- if (
        "Value" %in% names(x)
      ) {
        as.character(
          x$Value[bad]
        )
      } else {
        rep(
          NA_character_,
          length(bad)
        )
      }

      row_number <- if (
        "Row" %in% names(x)
      ) {
        as.integer(
          x$Row[bad]
        )
      } else {
        as.integer(bad)
      }

      pieces[[length(pieces) + 1L]] <-
        data.frame(
          Rule = rule_name,
          Variable = variable,
          Row = row_number,
          Value = value,
          stringsAsFactors = FALSE
        )
    }

    if (length(pieces) == 0L) {

      return(
        data.frame(
          Rule = character(),
          Variable = character(),
          Row = integer(),
          Value = character(),
          stringsAsFactors = FALSE
        )
      )
    }

    do.call(
      rbind,
      pieces
    )
  }

  #---------------------------------------------
  # Collect violations
  #---------------------------------------------
  violations <- rbind(
    collect_violations(
      object$range,
      "Range"
    ),
    collect_violations(
      object$category,
      "Category"
    ),
    collect_violations(
      object$unique,
      "Unique"
    ),
    collect_violations(
      object$required,
      "Required"
    ),
    collect_violations(
      object$pattern,
      "Pattern"
    )
  )

  rownames(violations) <- NULL

  #---------------------------------------------
  # Construct result
  #---------------------------------------------
  result <- list(
    status = object$status,
    total_violations =
      object$total_violations,
    by_rule = object$summary,
    violations = violations
  )

  class(result) <- c(
    "summary.DataAuditRuleResult",
    "list"
  )

  result
}
