test_that("get_structure_level works for each glycan separately", {
  glycan1 <- as_glycan_structure("Gal(b1-3)GalNAc(a1-")
  glycan2 <- as_glycan_structure("Gal(b1-?)GalNAc(a1-")
  glycan3 <- as_glycan_structure("Gal(??-?)GalNAc(??-")
  glycan4 <- as_glycan_structure("Hex(??-?)HexNAc(??-")
  glycan5 <- as_glycan_structure("Hex(b1-3)HexNAc(a1-")

  expect_equal(get_structure_level(glycan1), "intact")
  expect_equal(get_structure_level(glycan2), "partial")
  expect_equal(get_structure_level(glycan3), "topological")
  expect_equal(get_structure_level(glycan4), "basic")
  expect_warning(
    expect_equal(get_structure_level(glycan5), "basic"),
    class = "glyrepr_warning_generic_structure_linkages"
  )
})

test_that("get_structure_level works for an intact glycan vector", {
  glycans <- as_glycan_structure(c(
    "Gal(b1-3)GalNAc(a1-",
    "GalNAc(a1-"
  ))
  expect_equal(get_structure_level(glycans), "intact")
})

test_that("get_structure_level works for a partial glycan vector with only one unknown linkage", {
  glycans <- as_glycan_structure(c(
    "Gal(b1-?)GalNAc(a1-",
    "GalNAc(a1-"
  ))
  expect_equal(get_structure_level(glycans), "partial")
})

test_that("get_structure_level works for a partial glycan vector with only one known linkage", {
  glycans <- as_glycan_structure(c(
    "Gal(?1-?)GalNAc(??-",
    "GalNAc(??-"
  ))
  expect_equal(get_structure_level(glycans), "partial")
})

test_that("get_structure_level works for a partial glycan vector with only one known reducing end configuration", {
  glycans <- as_glycan_structure(c(
    "Gal(??-?)GalNAc(??-",
    "GalNAc(?1-"
  ))
  expect_equal(get_structure_level(glycans), "partial")
})

test_that("get_structure_level works for a topological glycan vector", {
  glycans <- as_glycan_structure(c(
    "Gal(??-?)GalNAc(??-",
    "GalNAc(??-"
  ))
  expect_equal(get_structure_level(glycans), "topological")
})

test_that("get_structure_level works for a basic glycan vector", {
  glycans <- as_glycan_structure(c(
    "Hex(??-?)HexNAc(??-",
    "HexNAc(??-"
  ))
  expect_equal(get_structure_level(glycans), "basic")
})

test_that("get_structure_level works for a basic glycan vector with linkages", {
  glycans <- as_glycan_structure(c(
    "Hex(b1-3)HexNAc(a1-",
    "HexNAc(a1-"
  ))
  expect_snapshot(res <- get_structure_level(glycans))
  # should warn about the rare case of a generic glycan with linkages,
  # and tell the user that it will be treated as basic

  expect_equal(res, "basic")
})

test_that("get_structure_level ignores NA", {
  glycans <- as_glycan_structure(c(
    "Hex(??-?)HexNAc(??-",
    "HexNAc(??-",
    NA
  ))
  expect_equal(get_structure_level(glycans), "basic")
})

test_that("get_structure_level return NA_character_ for all-NA vector", {
  glycans <- as_glycan_structure(c(NA, NA))
  expect_equal(get_structure_level(glycans), NA_character_)
})

test_that("get_structure_level returns NA_character_ for empty vector", {
  glycans <- as_glycan_structure(character())
  expect_equal(get_structure_level(glycans), NA_character_)
})

test_that("reduce_structure_level works for each glycan separately", {
  glycan_intact <- as_glycan_structure("Gal(b1-3)GalNAc(a1-")
  glycan_partial <- as_glycan_structure("Gal(b1-?)GalNAc(a1-")
  glycan_topological <- as_glycan_structure("Gal(??-?)GalNAc(??-")

  # intact to topological
  expect_equal(
    as.character(reduce_structure_level(
      glycan_intact,
      to_level = "topological"
    )),
    "Gal(??-?)GalNAc(??-"
  )
  # partial to topological
  expect_equal(
    as.character(reduce_structure_level(
      glycan_partial,
      to_level = "topological"
    )),
    "Gal(??-?)GalNAc(??-"
  )
  # topological to topological (identity)
  expect_equal(
    as.character(reduce_structure_level(
      glycan_topological,
      to_level = "topological"
    )),
    "Gal(??-?)GalNAc(??-"
  )

  # intact to basic
  expect_equal(
    as.character(reduce_structure_level(glycan_intact, to_level = "basic")),
    "Hex(??-?)HexNAc(??-"
  )
  # partial to basic
  expect_equal(
    as.character(reduce_structure_level(glycan_partial, to_level = "basic")),
    "Hex(??-?)HexNAc(??-"
  )
  # topological to basic
  expect_equal(
    as.character(reduce_structure_level(
      glycan_topological,
      to_level = "basic"
    )),
    "Hex(??-?)HexNAc(??-"
  )
})

test_that("reduce_structure_level rejects higher level", {
  glycan <- as_glycan_structure("Hex(??-?)HexNAc(??-")
  expect_snapshot(
    reduce_structure_level(glycan, to_level = "topological"),
    error = TRUE
  )
})

test_that("reduce_structure_level works for multiple glycans", {
  glycans <- as_glycan_structure(c(
    "Gal(b1-3)GalNAc(a1-",
    "Gal(b1-?)GalNAc(a1-",
    "Gal(??-?)GalNAc(??-"
  ))
  expect_equal(
    as.character(reduce_structure_level(glycans, to_level = "topological")),
    c("Gal(??-?)GalNAc(??-", "Gal(??-?)GalNAc(??-", "Gal(??-?)GalNAc(??-")
  )
})

test_that("reduce_structure_level works for all-NA vectors", {
  glycans <- as_glycan_structure(c(NA, NA))
  expect_equal(reduce_structure_level(glycans, to_level = "topological"), glycans)
})

test_that("reduce_structure_level works for empty vectors", {
  glycans <- as_glycan_structure(character())
  expect_equal(reduce_structure_level(glycans, to_level = "topological"), glycans)
})