library(testthat)
library(DataAudit)

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

test_that("data_overview returns DataOverview object", {

  result <- data_overview(iris)

  expect_s3_class(
    result,
    "DataOverview"
  )

})

test_that("data_overview returns list", {

  result <- data_overview(iris)

  expect_true(
    is.list(result)
  )

})

test_that("data_overview contains expected components", {

  result <- data_overview(iris)

  expected <- c(
    "Rows",
    "Variables",
    "TotalCells",
    "MissingCells",
    "CompleteCells",
    "Completeness",
    "CompleteCases",
    "DuplicateRows",
    "NumericVariables",
    "FactorVariables",
    "CharacterVariables",
    "LogicalVariables",
    "DateVariables",
    "DateTimeVariables"
  )

  expect_true(
    all(expected %in% names(result))
  )

})


#==========================================================
# iris dataset
#==========================================================

test_that("data_overview reports correct iris dimensions", {

  result <- data_overview(iris)

  expect_equal(
    result$Rows,
    150L
  )

  expect_equal(
    result$Variables,
    5L
  )

})

test_that("data_overview reports correct total cells", {

  result <- data_overview(iris)

  expect_equal(
    result$TotalCells,
    750L
  )

})

test_that("data_overview reports no missing cells for iris", {

  result <- data_overview(iris)

  expect_equal(
    result$MissingCells,
    0L
  )

  expect_equal(
    result$CompleteCells,
    750L
  )

  expect_equal(
    result$Completeness,
    100
  )

})

test_that("data_overview reports complete cases correctly", {

  result <- data_overview(iris)

  expect_equal(
    result$CompleteCases,
    150L
  )

})

test_that("data_overview reports iris variable types", {

  result <- data_overview(iris)

  expect_equal(
    result$NumericVariables,
    4L
  )

  expect_equal(
    result$FactorVariables,
    1L
  )

  expect_equal(
    result$CharacterVariables,
    0L
  )

  expect_equal(
    result$LogicalVariables,
    0L
  )

})


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

test_that("data_overview calculates missing values correctly", {

  dat <- iris

  dat$Sepal.Length[1:10] <- NA
  dat$Species[1:5] <- NA

  result <- data_overview(dat)

  expect_equal(
    result$MissingCells,
    15L
  )

  expect_equal(
    result$CompleteCells,
    735L
  )

})

test_that("data_overview calculates completeness correctly", {

  dat <- data.frame(
    x = c(1, NA),
    y = c(1, 2)
  )

  result <- data_overview(dat)

  expect_equal(
    result$TotalCells,
    4L
  )

  expect_equal(
    result$MissingCells,
    1L
  )

  expect_equal(
    result$Completeness,
    75
  )

})

test_that("data_overview calculates complete cases with missing data", {

  dat <- data.frame(
    x = c(1, NA, 3),
    y = c(1, 2, NA)
  )

  result <- data_overview(dat)

  expect_equal(
    result$CompleteCases,
    1L
  )

})


#==========================================================
# Duplicate rows
#==========================================================

test_that("data_overview detects duplicate rows", {

  dat <- data.frame(
    x = c(1, 2, 2, 3),
    y = c("A", "B", "B", "C")
  )

  result <- data_overview(dat)

  expect_equal(
    result$DuplicateRows,
    1L
  )

})

test_that("data_overview reports no duplicates when absent", {

  dat <- data.frame(
    x = 1:5,
    y = letters[1:5]
  )

  result <- data_overview(dat)

  expect_equal(
    result$DuplicateRows,
    0L
  )

})


#==========================================================
# Variable types
#==========================================================

test_that("data_overview identifies character variables", {

  dat <- data.frame(
    x = c("A", "B", "C"),
    stringsAsFactors = FALSE
  )

  result <- data_overview(dat)

  expect_equal(
    result$CharacterVariables,
    1L
  )

})

test_that("data_overview identifies factor variables", {

  dat <- data.frame(
    x = factor(c("A", "B", "C"))
  )

  result <- data_overview(dat)

  expect_equal(
    result$FactorVariables,
    1L
  )

})

test_that("data_overview identifies logical variables", {

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

  result <- data_overview(dat)

  expect_equal(
    result$LogicalVariables,
    1L
  )

})

test_that("data_overview identifies Date variables", {

  dat <- data.frame(
    date = as.Date("2026-01-01") + 0:4
  )

  result <- data_overview(dat)

  expect_equal(
    result$DateVariables,
    1L
  )

})

test_that("data_overview identifies POSIXct variables", {

  dat <- data.frame(
    time = as.POSIXct(
      "2026-01-01 00:00:00",
      tz = "UTC"
    ) + 0:4
  )

  result <- data_overview(dat)

  expect_equal(
    result$DateTimeVariables,
    1L
  )

})

test_that("data_overview handles mixed variable types", {

  dat <- data.frame(
    numeric = 1:5,
    character = letters[1:5],
    factor = factor(LETTERS[1:5]),
    logical = c(TRUE, FALSE, TRUE, FALSE, TRUE),
    date = as.Date("2026-01-01") + 0:4,
    stringsAsFactors = FALSE
  )

  result <- data_overview(dat)

  expect_equal(result$NumericVariables, 1L)
  expect_equal(result$CharacterVariables, 1L)
  expect_equal(result$FactorVariables, 1L)
  expect_equal(result$LogicalVariables, 1L)
  expect_equal(result$DateVariables, 1L)

})


#==========================================================
# One-column data
#==========================================================

test_that("data_overview works with one-column data", {

  dat <- data.frame(
    x = 1:10
  )

  result <- data_overview(dat)

  expect_equal(
    result$Rows,
    10L
  )

  expect_equal(
    result$Variables,
    1L
  )

})


#==========================================================
# Zero-row data
#==========================================================

test_that("data_overview works with zero-row data.frame", {

  dat <- data.frame(
    x = numeric(0),
    y = character(0)
  )

  result <- data_overview(dat)

  expect_equal(
    result$Rows,
    0L
  )

  expect_equal(
    result$Variables,
    2L
  )

  expect_equal(
    result$TotalCells,
    0L
  )

  expect_true(
    is.na(result$Completeness)
  )

  expect_equal(
    result$CompleteCases,
    0L
  )

})


#==========================================================
# Tibble
#==========================================================

test_that("data_overview works with tibble", {

  skip_if_not_installed("tibble")

  dat <- tibble::as_tibble(iris)

  result <- data_overview(dat)

  expect_s3_class(
    result,
    "DataOverview"
  )

  expect_equal(
    result$Rows,
    150L
  )

})


#==========================================================
# Invalid input
#==========================================================

test_that("data_overview rejects NULL", {

  expect_error(
    data_overview(NULL),
    "'data' cannot be NULL"
  )

})

test_that("data_overview rejects numeric vector", {

  expect_error(
    data_overview(1:10),
    "'data' must be a data.frame"
  )

})

test_that("data_overview rejects character vector", {

  expect_error(
    data_overview(letters),
    "'data' must be a data.frame"
  )

})

test_that("data_overview rejects list", {

  expect_error(
    data_overview(
      list(
        x = 1:10,
        y = 11:20
      )
    ),
    "'data' must be a data.frame"
  )

})

test_that("data_overview rejects empty data.frame", {

  expect_error(
    data_overview(
      data.frame()
    ),
    "at least one variable"
  )

})
