#' Score-Based Slow Digestibility Index
#'
#' Computes the score-based slow digestibility index using criterion-wise
#' scoring followed by min-max normalization.
#'
#' @param Data A data frame or object coercible to a data frame. The first
#'   column must contain candidate names.
#' @param type A character vector containing `+` and `-` signs to indicate
#'   benefit and cost criteria, respectively. Its length must match the number
#'   of criteria columns.
#'
#' @return A data frame with two columns:
#' \describe{
#'   \item{Score}{TOPSIS score}
#'   \item{Rank}{Rank}
#' }
#'
#' @details For each criterion, the score is computed relative to the observed
#'   maximum for benefit criteria and the observed minimum for cost criteria.
#'   The final score is obtained by averaging the criterion-wise scores for each
#'   candidate and applying min-max normalization.
#'@references
#' Pandey, S., Goswami, D., Vinutha, T., Goswami, S., Kumar, R. R., Singh, S. P., Rudra, S. G., Singh, M. K., Satyavathi, T., Girija, A., Thandapilly, S. J., & Krishnan, V. (2026). Molecular and microstructural cues for starch digestive heterogeneity in Indian pearl millet (Pennisetum glaucum). Journal of Functional Foods, 138, 107208. https://doi.org/10.1016/j.jff.2026.107208.
#' @examples
#' \donttest{
#' simulate_new_crop_data <- function(n_rep = 20, seed = 123) {
#' crop_names <- c("Sample 1", "Sample 2", "Sample 3", "Sample 4", "Sample 5")
#'  sim_one_crop <- function(crop, n) {
#'    data.frame(
#'      Crop = rep(crop, n),
#'      `TS %` = runif(n, 40, 80),
#'      Aratio = runif(n, 0.30, 2.50),
#'      `TAC%` = runif(n, 20, 35),
#'      `TAPC%` = runif(n, 10, 60),
#'      `RDS %` = runif(n, 35, 75),
#'      `SDS%` = runif(n, 5, 25),
#'      `RS%` = runif(n, 10, 45),
#'      `RC%` = runif(n, 15, 35),
#'      `Total Protein` = runif(n, 5, 25),
#'      `Total Oil` = runif(n, 1, 10),
#'      `Total Phenolic` = runif(n, 0.5, 7.5),
#'      PV = runif(n, 800, 6000),
#'      PT = runif(n, 60, 75),
#'      HS = runif(n, 700, 5000),
#'      FV = runif(n, 1500, 9000),
#'      check.names = FALSE
#'    )
#'  }
#'  simulated_data <- do.call(
#'    rbind,
#'    lapply(crop_names, sim_one_crop, n = n_rep)
#'  )
#'  numeric_cols <- setdiff(names(simulated_data), "Crop")
#'  simulated_data[numeric_cols] <- round(simulated_data[numeric_cols], 3)
#'   rownames(simulated_data) <- NULL
#'   simulated_data
#' }
#' Data <- simulate_new_crop_data(n_rep = 1, seed = 123)
#' tp <- c("+", "+", "+", "-", "-", "+", "-", "+", "+", "+", "+", "-", "+", "+", "+")
#' scoreSDI(Data, type = tp)
#' }
#' @export
#'
scoreSDI <- function(Data, type) {

  Data <- as.data.frame(Data)

  if (ncol(Data) < 2) {
    stop("Data must contain at least one candidate column and one numeric variable column.")
  }

  candidate<-NULL
  colnames(Data)[1] <- "candidate"

  decision_data <- Data[, -1, drop = FALSE]

  if (!all(sapply(decision_data, is.numeric))) {
    stop("All criteria columns must be numeric.")
  }

  if (length(type) != ncol(decision_data)) {
    stop("Length of type must be equal to the number of criteria columns.")
  }

  if (!all(type %in% c("+", "-"))) {
    stop("type must contain only '+' and '-'.")
  }

  candidate_names <- unique(Data$candidate)
  n_candidate <- length(candidate_names)
  n_criteria <- ncol(decision_data)

  raw_mean <- NULL

  for (i in seq_len(n_candidate)) {

    candidate_data <- subset(Data, candidate == candidate_names[i])
    candidate_score <- NULL

    for (j in seq_len(n_criteria)) {

      criterion_values <- candidate_data[, j + 1]

      if (type[j] == "+") {
        score_value <- mean(criterion_values / max(decision_data[, j]))
      } else {
        score_value <- mean(min(decision_data[, j]) / criterion_values)
      }

      candidate_score <- cbind(candidate_score, score_value)
    }

    raw_mean <- rbind(raw_mean, candidate_score)
  }

  rownames(raw_mean) <- candidate_names
  colnames(raw_mean) <- colnames(decision_data)

  min_max_norm <- function(x) {
    if (max(x) == min(x)) {
      return(rep(0, length(x)))
    }
    (x - min(x)) / (max(x) - min(x))
  }

  final_score <- min_max_norm(rowMeans(raw_mean))
  final_rank <- rank(-final_score, ties.method = "min")

  Index <- data.frame(
    Score = round(final_score, 3),
    Rank = final_rank
  )

  rownames(Index) <- candidate_names

  return(Index)
}
