#==========================================================
# Unique Identifier Check
#==========================================================

#' Check Unique Identifier
#'
#' Evaluates whether a variable can serve as a unique
#' identifier by checking for missing and duplicated values.
#'
#' @param data A data.frame.
#' @param variable A single character string specifying the
#'   variable to check.
#'
#' @return A data.frame of class \code{UniqueCheck}
#'   containing row-level uniqueness diagnostics.
#'
#' @details
#' Each observation is evaluated for missing and duplicated
#' identifier values.
#'
#' A value is considered duplicated when it occurs more than
#' once among non-missing observations. All occurrences of a
#' repeated value are flagged.
#'
#' Missing values are flagged separately and are not treated
#' as duplicated values.
#'
#' The output contains:
#'
#' \itemize{
#'   \item \code{Row}: row number.
#'   \item \code{Value}: identifier value.
#'   \item \code{Missing}: whether the value is missing.
#'   \item \code{Duplicate}: whether the non-missing value
#'     occurs more than once.
#'   \item \code{ValidUnique}: whether the value is both
#'     non-missing and unique.
#' }
#'
#' @examples
#' dat <- data.frame(
#'   Animal_ID = c(101, 102, 102, 103, NA)
#' )
#'
#' unique_check(
#'   dat,
#'   "Animal_ID"
#' )
#'
#' @export

unique_check <- function(data, variable) {

  #---------------------------------------------
  # Validate data
  #---------------------------------------------
  validate_data(data)

  #---------------------------------------------
  # Validate variable
  #---------------------------------------------
  if (missing(variable) ||
      !is.character(variable) ||
      length(variable) != 1L ||
      is.na(variable) ||
      !nzchar(variable)) {

    stop(
      "'variable' must be a single non-empty character string.",
      call. = FALSE
    )
  }

  #---------------------------------------------
  # Check variable exists
  #---------------------------------------------
  if (!variable %in% names(data)) {

    stop(
      sprintf(
        "Variable '%s' was not found in 'data'.",
        variable
      ),
      call. = FALSE
    )
  }

  #---------------------------------------------
  # Extract variable
  #---------------------------------------------
  x <- data[[variable]]

  #---------------------------------------------
  # Missing values
  #---------------------------------------------
  missing_value <- is.na(x)

  #---------------------------------------------
  # Duplicated values
  #
  # duplicated(x) detects later duplicates.
  # duplicated(x, fromLast = TRUE) detects
  # earlier occurrences.
  #
  # Combining both flags every occurrence of a
  # repeated non-missing value.
  #---------------------------------------------
  duplicate_value <-
    !missing_value &
    (
      duplicated(x) |
        duplicated(
          x,
          fromLast = TRUE
        )
    )

  #---------------------------------------------
  # Valid unique identifier
  #---------------------------------------------
  valid_unique <-
    !missing_value &
    !duplicate_value

  #---------------------------------------------
  # Construct result
  #---------------------------------------------
  result <- data.frame(
    Row = seq_along(x),
    Value = x,
    Missing = missing_value,
    Duplicate = duplicate_value,
    ValidUnique = valid_unique,
    stringsAsFactors = FALSE,
    check.names = FALSE
  )

  #---------------------------------------------
  # Class
  #---------------------------------------------
  class(result) <- c(
    "UniqueCheck",
    "data.frame"
  )

  result
}
