
#' Generalised Slow Digestibility Index
#'
#' Computes the generalised slow digestibility index using TOPSIS with
#' user-defined weights and criterion type.
#'
#' @param Data A data frame or object coercible to a data frame. The first
#'   column must contain candidate names. The remaining numeric columns of parameters.
#' @param weights A numeric vector of criterion weights. Its length must match
#'   the number of criteria columns.
#' @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 This function computes the generalised slow digestibility index
#'   using the Technique for Order Preference by Similarity to Ideal Solution
#'   (TOPSIS). The first column of the input data is treated as the candidate
#'   identifier, while the remaining columns are treated as numeric evaluation
#'   criteria. User-supplied weights and criterion type are used to calculate
#'   the final index score and ranking.
#'
#' @import topsis
#'@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),
#'      `IGP%` = runif(n, 65, 100),
#'      `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)
#' wt <- c(0.105, 0.105, 0.0875, 0.0525, 0.075, 0.075, 0.075, 0.075,
#'         0.15, 0.04, 0.04, 0.02, 0.025, 0.025, 0.025, 0.025)
#' tp <- c("+", "+", "+", "-", "-", "+", "+", "-", "+", "+", "+", "+", "-", "+", "+", "+")
#' genSDI(Data, weights = wt, type = tp)
#'}
#' @export
#'
genSDI <- function(Data, weights, type) {

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

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

  decision_data <- as.data.frame(Data[, -1])
  rownames(decision_data) <- as.character(Data$candidate)

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

  decision_matrix <- as.matrix(decision_data)

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

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

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

  if (abs(sum(weights) - 1) > 1e-8) {
    stop("weights do not sum to 1.")
  }

  Index <- topsis(decision_matrix, weights, type)[, -1]
  Index$score <- round(Index$score, digits = 3)
  rownames(Index) <- as.character(Data$candidate)
  colnames(Index) <- c("Score", "Rank")

  return(Index)
}

