tempdir_file <- sanitize_path(withr::local_tempdir())
withr::local_envvar(R_USER_CACHE_DIR = tempdir_file)
# labelled_to_raw_project (Internal)
test_that("labelled_to_raw_project and raw_to_labelled_project works!", {
  project <- mock_test_project()$.internal
  # ensure project is marked as labelled and has labelled values
  expect_true(project$settings$labelled)
  # sanity check: labelled value present in example form
  expect_all_true(project$data$other$var_yesno %in% c("Yes", "No"))
  # convert and capture returned project
  expect_no_error({
    project_converted <- labelled_to_raw_project(project)
  })
  # internals updated
  expect_false(project_converted$settings$labelled)
  # values converted from labelled ("Yes"/"No") to raw codes ("1"/"0")
  expect_all_true(project_converted$data$other$var_yesno %in% c("0", "1"))
  expect_no_error({
    project_again <- raw_to_labelled_project(project_converted)
  })
  expect_all_true(project_again$data$other$var_yesno %in% c("Yes", "No"))
})
# labelled_to_raw_form (Internal)
test_that("labelled_to_raw_form and raw_to_labelled_form works!", {
  project <- mock_test_project()$.internal
  project_summary <- load_project_dataset(project, "REDCapSync") |>
    data_list_to_save()
  merged <- all_character_cols(project_summary$merged)
  var_yesno_labelled <- merged$var_yesno
  values <- unique(merged$var_yesno)
  expect_vector(values, size = 2L)
  expect_contains(values, c("Yes", "No"))
  merged <- labelled_to_raw_form(merged, project)
  var_yesno_coded <- merged$var_yesno
  values <- unique(merged$var_yesno)
  expect_vector(values, size = 2L)
  expect_contains(values, c("1", "0"))
  var_yesno_labelled_check <- (var_yesno_labelled == "Yes") |>
    as.integer() |>
    as.character()
  expect_identical(var_yesno_labelled_check, var_yesno_coded)
  merged <- raw_to_labelled_form(merged, project)
  var_yesno_labelled_again <- merged$var_yesno
  values <- unique(merged$var_yesno)
  expect_vector(values, size = 2L)
  expect_contains(values, c("Yes", "No"))
  expect_identical(var_yesno_labelled, var_yesno_labelled_again)
  expect_in("Unknown", project$metadata$missing_codes$name)
  labelled <- select(merged, record_id, var_branching)
  labelled$var_branching[3L] <- "Unknown"
  labelled$var_branching[5L] <- "Not applicable"
  raw <- labelled_to_raw_form(labelled, project)
  expect_identical(raw$var_branching[3L], "UNK")
  expect_identical(raw$var_branching[5L], "NA")
  labelled <- raw_to_labelled_form(raw, project)
  expect_identical(labelled$var_branching[3L], "Unknown")
  expect_identical(labelled$var_branching[5L], "Not applicable")
  mismatch <- select(merged, record_id, var_branching)
  mismatch$var_branching[3L] <- "Random Thing"
  error_message <- "Mismatched REDCap"
  expect_error(labelled_to_raw_form(mismatch, project), error_message)
  raw_mismatch <- raw
  raw_mismatch$var_branching[3L] <- "Random Thing"
  expect_message(raw_to_labelled_form(raw_mismatch, project), error_message)
  project$metadata$has_coding_conflicts <- TRUE
  error_text <- "you have a coding conflict"
  expect_error(raw_to_labelled_form(raw_mismatch, project), error_text)
})
# normalize_redcap (Internal)
test_that("normalize_redcap works with classic project", {
  project <- mock_test_project()$.internal
  call_list <- mock_test_calls()
  denormalized <- call_list$data
  result <- normalize_redcap(denormalized, project, labelled = TRUE)
  expect_type(result, type = "list")
  form_names <- names(result)
  expected_forms <- project$metadata$forms$form_name
  expect_all_true(expected_forms %in% form_names)
  expect_all_true(unlist(lapply(result, is.data.frame)))
  id_col <- project$metadata$id_col
  fields <- project$metadata$fields
  fields <- fields[which(fields$field_name != id_col), ]
  text_fields <- fields$field_name[which(fields$form_name == "text")]
  expect_true(id_col %in% colnames(result$text))
  expect_all_true(text_fields %in% colnames(result$text))
  rows_x <- which(fields$form_name == "other" &
                    (!fields$field_type %in% FIELD_TYPES_NOT_IN_DATA))
  other_fields <- fields$field_name[rows_x]
  expect_all_true(other_fields %in% colnames(result$other))
  expect_all_false(text_fields %in% colnames(result$other))
  expect_all_false(other_fields %in% colnames(result$text))
})
test_that("normalize_redcap works with longitudinal project", {
  project_name <- "TEST_REDCAPR_LONGITUDINAL"
  project <- mock_test_project(project_name)$.internal
  call_list <- mock_test_calls(project_name)
  denormalized <- call_list$data
  result <- normalize_redcap(denormalized, project, labelled = TRUE)
  expect_true(project$metadata$is_longitudinal)
  expect_type(result, type = "list")
  form_names <- names(result)
  expected_forms <- project$metadata$forms$form_name
  expect_all_true(expected_forms %in% form_names)
  expect_all_true(unlist(lapply(result, is.data.frame)))
  id_col <- project$metadata$id_col
  fields <- project$metadata$fields
  expect_true(id_col %in% colnames(result$demographics))
  field_rows <- which(fields$form_name == "demographics" &
                        (!fields$field_type %in% FIELD_TYPES_NOT_IN_DATA))
  fields_to_check <- fields$field_name[field_rows]
  expect_all_true(fields_to_check %in% colnames(result$demographics))
  fields <- fields[which(fields$field_name != id_col), ]
  field_rows <-  which(fields$form_name == "demographics" &
                         (!fields$field_type %in% FIELD_TYPES_NOT_IN_DATA))
  fields_to_check <- fields$field_name[field_rows]
  expect_all_true(fields_to_check %in% colnames(result$demographics))
  expect_all_false(fields_to_check %in% colnames(result$other))
  expect_all_false(fields_to_check %in% colnames(result$text))
})
test_that("normalize_redcap works with repeating project", {
  project_name <- "TEST_REPEATING"
  project <- mock_test_project(project_name)$.internal
  call_list <- mock_test_calls(project_name)
  denormalized <- call_list$data
  result <- normalize_redcap(denormalized, project, labelled = TRUE)
  expect_false(project$metadata$is_longitudinal)
  expect_type(result, type = "list")
  form_names <- names(result)
  expected_forms <- project$metadata$forms$form_name
  expect_all_true(expected_forms %in% form_names)
  expect_all_true(unlist(lapply(result, is.data.frame)))
  id_col <- project$metadata$id_col
  fields <- project$metadata$fields
  expect_true(id_col %in% colnames(result$form_1))
  field_rows <- which(fields$form_name == "form_1" &
                        (!fields$field_type %in% FIELD_TYPES_NOT_IN_DATA))
  fields_to_check <- fields$field_name[field_rows]
  expect_all_true(fields_to_check %in% colnames(result$form_1))
  extra_cols <- c("record_id",
                  "redcap_repeat_instrument",
                  "redcap_repeat_instance")
  field_rows <-  which(fields$form_name == "repeating" &
                         (!fields$field_type %in% FIELD_TYPES_NOT_IN_DATA))
  fields_to_check <- unique(append(extra_cols, fields$field_name[field_rows]))
  expect_all_true(fields_to_check %in% colnames(result$repeating))
  field_rows <-  which(fields$form_name == "repeating_2" &
                         (!fields$field_type %in% FIELD_TYPES_NOT_IN_DATA))
  fields_to_check <- unique(append(extra_cols, fields$field_name[field_rows]))
  expect_all_true(fields_to_check %in% colnames(result$repeating_2))
})
# raw_to_labelled_project (Internal)
test_that("raw_to_labelled_project works!", {
})
# raw_to_labelled_form (Internal)
test_that("raw_to_labelled_form works!", {
})
# construct_header_list (Internal)
test_that("construct_header_list works!", {
})
# extract_project_records (Internal)
test_that("extract_project_records works!", {
})
# extract_values_from_form_list (Internal)
test_that("extract_values_from_form_list works!", {
})
# field_names_metadata (Internal)
test_that("field_names_metadata works!", {
})
# field_to_form_names (Internal)
test_that("field_to_form_names works!", {
})
# filter_fields_from_form (Internal)
test_that("filter_fields_from_form works!", {
  project <- mock_test_project("TEST_REPEATING")$.internal
  form <- bind_rows(project$data$repeating, project$data$repeating_2)
  expect_error(filter_fields_from_form(form, project))
  expect_error(filter_fields_from_form(form, project))
  form <- project$data$form_1
  expect_no_error(filter_fields_from_form(form, project))
  fields <- filter_fields_from_form(form, project)
  expect_data_frame(fields, nrows = ncol(form))
})
# generate_choices_table (Internal)
test_that("generate_choices_table works!", {
})
# get_all_field_names (Internal)
test_that("get_all_field_names works!", {
  project <- mock_test_project()$.internal
  field_names <- get_all_field_names(project)
  expect_all_true(field_names %in% project$metadata$fields$field_name)
})
# get_identifier_fields (Internal)
test_that("get_identifier_fields works!", {
  # minimal metadata/fields to exercise deidentified / strict / super_strict
  field_names <- c("record_id", "email", "cell", "dob", "other", "notes", "int")
  valid_types <- c(NA, "email", "phone", "date_mdy", NA, NA, "integer")
  fields <- data.frame(
    field_name = field_names,
    identifier = c("y", NA, NA, "y", NA, NA, NA),
    field_type = c("text", "text", "text", "text", "text", "notes", "text"),
    text_validation_type_or_show_slider_number = valid_types,
    stringsAsFactors = FALSE
  )
  data_list <- list(metadata = list(fields = fields))
  data_list$metadata$form_key_cols <- "record_id"
  # deidentified: only explicit identifier flagged "y"
  out_deid <- get_identifier_fields(data_list, get_type = "deidentified")
  expect_identical(out_deid, c("record_id", "dob"))
  # deidentified_strict: includes fields with validation types
  # in strict list (email, phone)
  out_strict <- get_identifier_fields(data_list = data_list,
                                      get_type = "deidentified_strict")
  expect_identical(out_strict, c("record_id", "email", "cell", "dob"))
  # deidentified_super_strict: includes additional validation  (dates, etc.)
  out_super <- get_identifier_fields(data_list = data_list,
                                     get_type = "deidentified_super_strict")
  expect_identical(out_super, setdiff(field_names, "int"))
  # invert = TRUE should return the complement set
  out_inv <- get_identifier_fields(data_list = data_list,
                                   get_type = "deidentified",
                                   invert = TRUE)
  expect_identical(out_inv, c("email", "cell", "other", "notes", "int"))
})
# get_key_col_list (Internal)
test_that("get_key_col_list works!", {
})
# get_min_dates (Internal)
test_that("get_min_dates works!", {
  # construct minimal data_list with date fields across forms
  data_list <- list(
    data = list(
      form1 = data.frame(
        record_id = c("1", "2"),
        date1 = c("2020-01-01", "2020-01-05"),
        stringsAsFactors = FALSE
      ),
      form2 = data.frame(
        record_id = c("2", "3"),
        date2 = c("2020-02-01", "2020-01-15"),
        stringsAsFactors = FALSE
      )
    ),
    metadata = list(
      fields = data.frame(
        field_name = c("record_id", "date1", "date2"),
        field_type_r = c(NA, "date", "date"),
        stringsAsFactors = FALSE
      ),
      form_key_cols = list(record_id = "record_id")
    )
  )
  out <- get_min_dates(data_list)
  # basic structure checks
  expect_data_frame(out, nrows = 3L, ncols = 2L)
  expect_true(all(c("record_id", "date") %in% colnames(out)))
  # values: min date per record across forms
  one <- as.character(out$date[match("1", out$record_id)])
  two <- as.character(out$date[match("2", out$record_id)])
  three <- as.character(out$date[match("3", out$record_id)])
  expect_identical(one, "2020-01-01")
  expect_identical(two, "2020-01-05")
  expect_identical(three, "2020-01-15")
})
# get_project_url (Internal)
test_that("get_project_url works!", {
  project <- mock_test_project()$.internal
  project <- update_project_links(project)
  e <- new.env(parent = emptyenv())
  # get_project_url
  e$url <- NULL
  local_mocked_bindings(
    browseURL = function(url) {
      e$url <- url
    }
  )
  for (link_type in LINK_TYPES) {
    e$url <- NULL
    get_project_url(project, link_type = link_type, open_browser = TRUE)
    expect_identical(e$url, project$links[[paste0("redcap_", link_type)]])
    out <- get_project_url(project, link_type = link_type, open_browser = FALSE)
    expect_identical(out, project$links[[paste0("redcap_", link_type)]])
  }
})
# get_record_url (Internal)
test_that("get_record_url works!", {
  project <- mock_test_project()$.internal
  project$links$redcap_base <- "https://fakeredcap.com/"
  expected_link <- paste0(
    project$links$redcap_base,
    "redcap_v",
    project$redcap$version,
    "/DataEntry/record_home.php?pid=",
    project$redcap$project_id
  )
  e <- new.env(parent = emptyenv())
  # get_project_url
  e$url <- NULL
  local_mocked_bindings(
    browseURL = function(url) {
      e$url <- url
    }
  )
  expect_identical(get_record_url(project, open_browser = FALSE), expected_link)
  expect_null(e$url) # does not call url
  e$url <- NULL
  get_record_url(project, open_browser = TRUE)
  expect_identical(e$url, expected_link)
  e$url <- NULL
  expect_error(get_record_url(project, record = "59", open_browser = FALSE),
               regexp = "is not one of the records")
  expect_identical(
    get_record_url(project, record = "1", open_browser = FALSE),
    paste0(expected_link, "&id=1")
  )
  expect_identical(
    get_record_url(project, page = "text", open_browser = FALSE),
    paste0(
      gsub("record_home", "index", expected_link, fixed = TRUE),
      "&page=text"
    )
  )
  expect_error(get_record_url(project, page = "text_2", open_browser = FALSE))
})
