# WARNING - Generated by {fusen} from dev/flat_scenario.Rmd: do not edit by hand # nolint: line_length_linter.

#' Create Exposure Scenario from a data.frame
#'
#' Like [create_scenario()] but takes an in-memory `data.frame` instead of an
#' Excel file, and each of the four treatment roles
#' (STEP / Collective / Initial / Supplementary) may hold a *vector* of process
#' names (a list-column), so a train can contain more than one process per role.
#'
#' Single-value role columns are also accepted (they behave like
#' [create_scenario()]); `NA` / empty roles are dropped from the train.
#'
#' @param user_input A data.frame / tibble with columns `CropName`, `Area`,
#'   `PopulationName`, `nb_population`, `PathName`, `nb_day_decay`, and the four
#'   treatment columns `STEPtreatmentName`, `CollectiveTreatmentName`,
#'   `InitialProcessName`, `SupplementaryProcessName`. Each treatment cell may be
#'   a single name, a character vector of names, `NA`, or empty.
#' @param config list config file, default value `config_ambre`.
#' @importFrom dplyr mutate pick
#' @importFrom purrr map pmap
#' @return A scenario tibble, same structure as [create_scenario()].
#' @export
#' @examples
#' df <- data.frame(
#'   CropName = "Tomato", Area = 35,
#'   PopulationName = "Maintenance staff", nb_population = 1,
#'   PathName = "Consumption of the final product tomato",
#'   nb_day_decay = NA_real_
#' )
#' df$STEPtreatmentName <- list(c("Q.1 - Activated Sludge", "Q.2 - Maturation Pond"))
#' df$CollectiveTreatmentName <- list(NA_character_)
#' df$InitialProcessName <- list("Q.6 - Chlorination")
#' df$SupplementaryProcessName <- list(NA_character_)
#' create_scenario_from_df(df)
create_scenario_from_df <- function(user_input, config = config_ambre) {
  if (!is.data.frame(user_input)) {
    stop("user_input must be a data.frame")
  }
  if (!is.numeric(user_input$Area)) {
    stop("Area must be a numeric value")
  }
  if (!is.numeric(user_input$nb_population)) {
    stop("nb_population must be a numeric value")
  }
  if (any(user_input$Area <= 0) || any(user_input$Area >= 10000)) {
    stop("Area must be strictly greater than 0 ha and smaller than 10,000 ha")
  }
  if (any(user_input$nb_population <= 0) ||
      any(user_input$nb_population >= 5000)) {
    stop("nb_population must be strictly greater than 0 and smaller than 5,000")
  }

  # add config file to each line
  scenario <- user_input |> mutate(config = list(config))

  # Single-value context columns (one crop / population / path per usage).
  scenario <- scenario |> mutate(
    CropID = as.numeric(map(.x = CropName, .f = ~ query_crop(cropName = .x))),
    CropHeight = as.numeric(map(.x = CropName, .f = ~ query_crop_height(cropName = .x))),
    PopulationID = as.numeric(map(.x = PopulationName, .f = ~ query_pop(popName = .x))),
    PathID = as.numeric(map(.x = PathName, .f = ~ query_exp_path(pathName = .x))),
    MatrixID = as.numeric(map(.x = PathName, .f = ~ query_matrix(pathName = .x)))
  )

  # Treatment roles: each cell may hold a vector of names -> a vector of IDs.
  # Resolve name-by-name (dropping NA) so names and IDs stay aligned and ordered
  # (query_barrier() on a vector would re-order to the processes-table order).
  # An empty role stays a scalar NA (like create_scenario()), so downstream code
  # that reads a single per-role ID (e.g. run_qmra_*() reading
  # SupplementaryProcessID) keeps working; a filled role becomes a vector of IDs.
  resolve_ids <- function(names) {
    names <- names[!is.na(names)]
    if (length(names) == 0) {
      return(NA_real_)
    }
    vapply(names, function(nm) query_barrier(barrierName = nm), numeric(1))
  }
  scenario <- scenario |> mutate(
    STEPtreatmentID = map(STEPtreatmentName, resolve_ids),
    CollectiveTreatmentID = map(CollectiveTreatmentName, resolve_ids),
    InitialProcessID = map(InitialProcessName, resolve_ids),
    SupplementaryProcessID = map(SupplementaryProcessName, resolve_ids)
  )

  # Trains: concatenate the role vectors, drop NA, keep order.
  drop_na_vec <- function(...) unname(c(...)[!is.na(c(...))])
  scenario <- scenario |> mutate(
    InitialTrainName = pmap(
      pick(STEPtreatmentName, CollectiveTreatmentName, InitialProcessName),
      drop_na_vec
    ),
    InitialTrainID = pmap(
      pick(STEPtreatmentID, CollectiveTreatmentID, InitialProcessID),
      drop_na_vec
    ),
    SupplementaryTrainName = pmap(
      pick(STEPtreatmentName, CollectiveTreatmentName, InitialProcessName, SupplementaryProcessName),
      drop_na_vec
    ),
    SupplementaryTrainID = pmap(
      pick(STEPtreatmentID, CollectiveTreatmentID, InitialProcessID, SupplementaryProcessID),
      drop_na_vec
    )
  )

  return(scenario)
}
