library(testthat)
library(DataAudit)


test_that("print DataAuditScore returns object invisibly", {

  report <- audit_data(
    data.frame(
      x = 1:5
    ),
    include_nzv = FALSE
  )

  score <- audit_score(report)

  result <- withVisible(
    print(score)
  )

  expect_false(
    result$visible
  )

  expect_identical(
    result$value,
    score
  )
})


test_that("print displays score header", {

  score <- audit_score(
    audit_data(
      data.frame(
        x = 1:5
      ),
      include_nzv = FALSE
    )
  )

  expect_output(
    print(score),
    "DataAudit Quality Score"
  )
})


test_that("print displays score and quality", {

  score <- audit_score(
    audit_data(
      data.frame(
        x = 1:5
      ),
      include_nzv = FALSE
    )
  )

  output <- capture.output(
    print(score)
  )

  expect_true(
    any(
      grepl(
        "Score:",
        output,
        fixed = TRUE
      )
    )
  )

  expect_true(
    any(
      grepl(
        "100.00 / 100",
        output,
        fixed = TRUE
      )
    )
  )

  expect_true(
    any(
      grepl(
        "Quality:",
        output,
        fixed = TRUE
      )
    )
  )

  expect_true(
    any(
      grepl(
        "Excellent",
        output,
        fixed = TRUE
      )
    )
  )
})


test_that("print displays dataset information", {

  score <- audit_score(
    audit_data(
      data.frame(
        x = 1:5,
        y = letters[1:5]
      ),
      include_nzv = FALSE
    )
  )

  output <- capture.output(
    print(score)
  )

  expect_true(
    any(
      grepl(
        "Dataset",
        output,
        fixed = TRUE
      )
    )
  )

  expect_true(
    any(
      grepl(
        "Rows:",
        output,
        fixed = TRUE
      )
    )
  )

  expect_true(
    any(
      grepl(
        "Variables:",
        output,
        fixed = TRUE
      )
    )
  )

  expect_true(
    any(
      grepl(
        "Data cells:",
        output,
        fixed = TRUE
      )
    )
  )
})


test_that("print displays issue information", {

  score <- audit_score(
    audit_data(
      data.frame(
        x = c(
          1,
          NA,
          Inf
        )
      ),
      include_nzv = FALSE
    )
  )

  output <- capture.output(
    print(score)
  )

  expect_true(
    any(
      grepl(
        "Automatic issues:",
        output,
        fixed = TRUE
      )
    )
  )

  expect_true(
    any(
      grepl(
        "Rule violations:",
        output,
        fixed = TRUE
      )
    )
  )

  expect_true(
    any(
      grepl(
        "Overall issues:",
        output,
        fixed = TRUE
      )
    )
  )
})


test_that("print displays custom rule violations", {

  dat <- data.frame(
    Age = c(
      5,
      40,
      -2
    )
  )

  report <- audit_data(
    dat,
    include_nzv = FALSE,
    rules = audit_rules(
      range = list(
        Age = c(0, 30)
      )
    )
  )

  score <- audit_score(report)

  output <- capture.output(
    print(score)
  )

  expect_true(
    any(
      grepl(
        "Rule violations:     2",
        output,
        fixed = TRUE
      )
    )
  )
})


test_that("print rejects malformed DataAuditScore", {

  x <- list()

  class(x) <- c(
    "DataAuditScore",
    "list"
  )

  expect_error(
    print(x),
    "Invalid 'DataAuditScore' object"
  )
})


test_that("print rejects object without DataAuditScore class", {

  x <- list(
    score = 100,
    quality = "Excellent",
    automatic_issues = 0L,
    rule_violations = 0L,
    overall_issues = 0L,
    rows = 5L,
    variables = 1L,
    total_cells = 5
  )

  expect_error(
    print.DataAuditScore(x),
    "Invalid 'DataAuditScore' object"
  )
})


test_that("print rejects invalid score", {

  score <- audit_score(
    audit_data(
      data.frame(
        x = 1:5
      ),
      include_nzv = FALSE
    )
  )

  score$score <- NA_real_

  expect_error(
    print(score),
    "Invalid score in 'DataAuditScore'"
  )
})


test_that("print rejects score above 100", {

  score <- audit_score(
    audit_data(
      data.frame(
        x = 1:5
      ),
      include_nzv = FALSE
    )
  )

  score$score <- 101

  expect_error(
    print(score),
    "Invalid score in 'DataAuditScore'"
  )
})


test_that("print rejects score below zero", {

  score <- audit_score(
    audit_data(
      data.frame(
        x = 1:5
      ),
      include_nzv = FALSE
    )
  )

  score$score <- -1

  expect_error(
    print(score),
    "Invalid score in 'DataAuditScore'"
  )
})


test_that("print rejects invalid quality category", {

  score <- audit_score(
    audit_data(
      data.frame(
        x = 1:5
      ),
      include_nzv = FALSE
    )
  )

  score$quality <- "Unknown"

  expect_error(
    print(score),
    "Invalid quality category in 'DataAuditScore'"
  )
})
