library(testthat)
library(DataAudit)


test_that("print method returns object invisibly", {

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

  rules <- audit_rules(
    range = list(
      Age = c(0, 30)
    )
  )

  result <- apply_audit_rules(
    dat,
    rules
  )

  returned <- withVisible(
    print(result)
  )

  expect_false(
    returned$visible
  )

  expect_identical(
    returned$value,
    result
  )
})


test_that("print method displays header", {

  result <- apply_audit_rules(
    data.frame(
      x = 1:3
    ),
    audit_rules()
  )

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

  expect_true(
    any(
      grepl(
        "DataAudit Rule Validation",
        output,
        fixed = TRUE
      )
    )
  )
})


test_that("print method displays status", {

  result <- apply_audit_rules(
    data.frame(
      x = 1:3
    ),
    audit_rules()
  )

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

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

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


test_that("print method displays total violations", {

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

  result <- apply_audit_rules(
    dat,
    audit_rules(
      range = list(
        Age = c(0, 30)
      )
    )
  )

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

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


test_that("print method displays rule summary", {

  result <- apply_audit_rules(
    data.frame(
      x = 1:3
    ),
    audit_rules()
  )

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

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

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


test_that("print method reports no violations", {

  result <- apply_audit_rules(
    data.frame(
      Age = c(
        5,
        10
      )
    ),
    audit_rules(
      range = list(
        Age = c(0, 30)
      )
    )
  )

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

  expect_true(
    any(
      grepl(
        "No rule violations detected.",
        output,
        fixed = TRUE
      )
    )
  )
})


test_that("print method reports range violation variable", {

  result <- apply_audit_rules(
    data.frame(
      Age = c(
        5,
        40
      )
    ),
    audit_rules(
      range = list(
        Age = c(0, 30)
      )
    )
  )

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

  expect_true(
    any(
      grepl(
        "Range: Age",
        output,
        fixed = TRUE
      )
    )
  )
})


test_that("print method reports all rule types", {

  dat <- data.frame(
    ID = c(
      "A001",
      "A001",
      "BAD"
    ),
    Species = c(
      "Dog",
      "Horse",
      ""
    ),
    Age = c(
      5,
      40,
      10
    ),
    stringsAsFactors = FALSE
  )

  rules <- audit_rules(
    range = list(
      Age = c(0, 30)
    ),
    category = list(
      Species = c(
        "Dog",
        "Cat"
      )
    ),
    unique = "ID",
    required = "Species",
    pattern = list(
      ID = "^A[0-9]{3}$"
    )
  )

  result <- apply_audit_rules(
    dat,
    rules
  )

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

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

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

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

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

  expect_true(
    any(grepl(
      "Pattern: ID",
      output,
      fixed = TRUE
    ))
  )
})


test_that("print rejects malformed result object", {

  x <- list()

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

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


test_that("print rejects malformed summary", {

  x <- list(
    status = "Passed",
    total_violations = 0L,
    summary = "invalid",
    range = list(),
    category = list(),
    unique = list(),
    required = list(),
    pattern = list()
  )

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

  expect_error(
    print(x),
    "Invalid rule summary"
  )
})


test_that("print rejects summary missing required columns", {

  x <- list(
    status = "Passed",
    total_violations = 0L,
    summary = data.frame(
      Rule = "Range"
    ),
    range = list(),
    category = list(),
    unique = list(),
    required = list(),
    pattern = list()
  )

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

  expect_error(
    print(x),
    "Invalid rule summary"
  )
})
