library(testthat)
library(DataAudit)

#==========================================================
# Basic output
#==========================================================

test_that("case_check returns CaseCheck", {

  dat <- data.frame(
    x = c("Dog", "Cat")
  )

  result <- case_check(
    dat,
    "x"
  )

  expect_s3_class(
    result,
    "CaseCheck"
  )

  expect_s3_class(
    result,
    "data.frame"
  )
})

test_that("case_check returns expected columns", {

  dat <- data.frame(
    x = c("Dog", "Cat")
  )

  result <- case_check(
    dat,
    "x"
  )

  expect_equal(
    names(result),
    c(
      "Row",
      "Value",
      "Normalized",
      "Missing",
      "CaseIssue",
      "ValidCase"
    )
  )
})

#==========================================================
# Normalization
#==========================================================

test_that("case_check normalizes values to lower case", {

  dat <- data.frame(
    x = c(
      "Dog",
      "DOG",
      "Cat"
    )
  )

  result <- case_check(
    dat,
    "x"
  )

  expect_equal(
    result$Normalized,
    c(
      "dog",
      "dog",
      "cat"
    )
  )
})

#==========================================================
# Case inconsistency
#==========================================================

test_that("case_check detects inconsistent case", {

  dat <- data.frame(
    x = c(
      "Dog",
      "dog",
      "DOG",
      "Cat"
    )
  )

  result <- case_check(
    dat,
    "x"
  )

  expect_equal(
    result$CaseIssue,
    c(
      TRUE,
      TRUE,
      TRUE,
      FALSE
    )
  )
})

test_that("all representations in inconsistent group are flagged", {

  dat <- data.frame(
    x = c(
      "Cattle",
      "cattle",
      "CATTLE",
      "Goat",
      "Goat"
    )
  )

  result <- case_check(
    dat,
    "x"
  )

  expect_equal(
    result$CaseIssue,
    c(
      TRUE,
      TRUE,
      TRUE,
      FALSE,
      FALSE
    )
  )
})

test_that("consistent repeated categories are not flagged", {

  dat <- data.frame(
    x = c(
      "Dog",
      "Dog",
      "Cat",
      "Cat"
    )
  )

  result <- case_check(
    dat,
    "x"
  )

  expect_false(
    any(result$CaseIssue)
  )

  expect_true(
    all(result$ValidCase)
  )
})

test_that("unique categories are not flagged", {

  dat <- data.frame(
    x = c(
      "Dog",
      "Cat",
      "Cattle"
    )
  )

  result <- case_check(
    dat,
    "x"
  )

  expect_false(
    any(result$CaseIssue)
  )
})

#==========================================================
# Missing values
#==========================================================

test_that("case_check handles missing values", {

  dat <- data.frame(
    x = c(
      "Dog",
      NA,
      "dog"
    )
  )

  result <- case_check(
    dat,
    "x"
  )

  expect_equal(
    result$Missing,
    c(
      FALSE,
      TRUE,
      FALSE
    )
  )

  expect_true(
    is.na(result$Normalized[2])
  )

  expect_false(
    result$CaseIssue[2]
  )

  expect_false(
    result$ValidCase[2]
  )
})

test_that("case_check handles all missing values", {

  dat <- data.frame(
    x = c(
      NA_character_,
      NA_character_,
      NA_character_
    )
  )

  result <- case_check(
    dat,
    "x"
  )

  expect_true(
    all(result$Missing)
  )

  expect_false(
    any(result$CaseIssue)
  )

  expect_false(
    any(result$ValidCase)
  )

  expect_true(
    all(is.na(result$Normalized))
  )
})

#==========================================================
# Factor variables
#==========================================================

test_that("case_check works with factors", {

  dat <- data.frame(
    x = factor(
      c(
        "Dog",
        "dog",
        "Cat"
      )
    )
  )

  result <- case_check(
    dat,
    "x"
  )

  expect_equal(
    result$CaseIssue,
    c(
      TRUE,
      TRUE,
      FALSE
    )
  )
})

#==========================================================
# Empty strings
#==========================================================

test_that("case_check handles empty strings", {

  dat <- data.frame(
    x = c(
      "",
      "",
      "Dog"
    )
  )

  result <- case_check(
    dat,
    "x"
  )

  expect_false(
    any(result$CaseIssue)
  )

  expect_equal(
    result$Normalized,
    c(
      "",
      "",
      "dog"
    )
  )
})

#==========================================================
# Internal spaces
#==========================================================

test_that("case_check preserves internal spaces", {

  dat <- data.frame(
    x = c(
      "Dairy Cattle",
      "dairy cattle",
      "Goat"
    )
  )

  result <- case_check(
    dat,
    "x"
  )

  expect_equal(
    result$CaseIssue,
    c(
      TRUE,
      TRUE,
      FALSE
    )
  )
})

#==========================================================
# Invalid variable
#==========================================================

test_that("case_check rejects missing variable", {

  expect_error(
    case_check(iris),
    "'variable' must be a single non-empty character string"
  )
})

test_that("case_check rejects NULL variable", {

  expect_error(
    case_check(
      iris,
      NULL
    ),
    "'variable' must be a single non-empty character string"
  )
})

test_that("case_check rejects empty variable", {

  expect_error(
    case_check(
      iris,
      ""
    ),
    "'variable' must be a single non-empty character string"
  )
})

test_that("case_check rejects numeric variable argument", {

  expect_error(
    case_check(
      iris,
      1
    ),
    "'variable' must be a single non-empty character string"
  )
})

test_that("case_check rejects multiple variable names", {

  expect_error(
    case_check(
      iris,
      c(
        "Species",
        "Sepal.Length"
      )
    ),
    "'variable' must be a single non-empty character string"
  )
})

test_that("case_check rejects NA variable", {

  expect_error(
    case_check(
      iris,
      NA_character_
    ),
    "'variable' must be a single non-empty character string"
  )
})

#==========================================================
# Unknown variable
#==========================================================

test_that("case_check rejects unknown variable", {

  expect_error(
    case_check(
      iris,
      "Unknown"
    ),
    "Variable 'Unknown' was not found in 'data'"
  )
})

#==========================================================
# Invalid variable type
#==========================================================

test_that("case_check rejects numeric column", {

  expect_error(
    case_check(
      iris,
      "Sepal.Length"
    ),
    "'variable' must refer to a character or factor variable"
  )
})

test_that("case_check rejects logical column", {

  dat <- data.frame(
    x = c(
      TRUE,
      FALSE
    )
  )

  expect_error(
    case_check(
      dat,
      "x"
    ),
    "'variable' must refer to a character or factor variable"
  )
})

test_that("case_check rejects Date column", {

  dat <- data.frame(
    x = as.Date(
      c(
        "2026-01-01",
        "2026-01-02"
      )
    )
  )

  expect_error(
    case_check(
      dat,
      "x"
    ),
    "'variable' must refer to a character or factor variable"
  )
})

#==========================================================
# Invalid data
#==========================================================

test_that("case_check rejects invalid data", {

  expect_error(
    case_check(
      NULL,
      "x"
    )
  )

  expect_error(
    case_check(
      1:5,
      "x"
    )
  )

  expect_error(
    case_check(
      list(x = "Dog"),
      "x"
    )
  )

  expect_error(
    case_check(
      data.frame(),
      "x"
    )
  )
})
