# -------------------------------------------------------------------------
# 1. Minimal in-memory workflow with custom ecoregions
# -------------------------------------------------------------------------

# Create two simple environmental layers on a small synthetic study area.
r1 <- terra::rast(
  ncols = 20, nrows = 20, xmin = 0, xmax = 10, ymin = 0, ymax = 10
)
terra::values(r1) <- rep(seq(0, 1, length.out = 20), each = 20)
r2 <- terra::rast(r1)
terra::values(r2) <- rep(seq(0, 1, length.out = 20), times = 20)
env <- c(r1, r2)

# Derive custom ecoregions and define a small occurrence table in memory.
eco <- make_ecoreg(env = env, nclass = 4)
occ <- data.frame(
  decimalLongitude = c(0.5, 1.2, 2.4, 3.6, 2.8, 6.0, 7.2, 7.4, 7.6, 8.8),
  decimalLatitude = c(1.0, 0.1, 2.3, 2.5, 2.7, 5.0, 7.1, 7.3, 6.5, 7.7)
)

# Build the range directly from the occurrence table and ecoregions.
range_obj <- get_range(
  occ_coord = occ,
  ecoreg = eco,
  verbose = FALSE
)

# Plot the predicted range and overlay the occurrence points.
terra::plot(range_obj$rangeOutput, col = 3, main = "Range Map")
graphics::points(occ, pch = 4)

\donttest{
# -------------------------------------------------------------------------
# 2. Typical online workflow with recent GBIF data
# -------------------------------------------------------------------------

# Download all GBIF occurrences for one species
obs <- get_gbif("Ailuropoda melanoleuca")

# Load a packaged terrestrial ecoregion layer
eco_terra <- read_ecoreg("eco_terra", save_dir = tempdir())

# Both calls above depend on remote services and return NULL or an empty
# table if those are unavailable, so guard the rest of this section
if (gbif_have(obs, eco_terra)) {

# Remove observation without data, i.e.,
# probably outdated for a threatned species such as the panda
obs <- obs[!is.na(obs$year), ]

# Inspect the GBIF backbone interpretation used by the package.
status <- get_status("Ailuropoda melanoleuca")
status

# Build the range.
panda_range <- get_range(
  occ_coord = obs,
  ecoreg = eco_terra,
  ecoreg_name = "ECO_NAME"
)

# Plot the predicted terrestrial range and the GBIF occurrences.
terra::plot(
  merge_range(panda_range),
  col = 3,
  main = paste("Range:", obs$scientificName[1])
)
graphics::points(
  obs$decimalLongitude,
  obs$decimalLatitude,
  pch = 4,
  col = grDevices::rgb(1, 0, 1, 0.2)
)

}

# -------------------------------------------------------------------------
# 3. Large downloaded GBIF table already stored on disk
# -------------------------------------------------------------------------

if (requireNamespace("data.table", quietly = TRUE)) {
  # Use the bundled GBIF-style example file as a stand-in for a large download.
  gbif_file <- system.file("extdata", "occ_example_2sps.csv", package = "gbif.range")

  # Keep each stage in its own temporary folder so outputs are easy to inspect.
  split_dir <- file.path(tempdir(), "gbif_pkg_split")
  occ_dir <- file.path(tempdir(), "gbif_pkg_occ_min")
  range_dir <- file.path(tempdir(), "gbif_pkg_ranges")

  # Remove earlier temporary outputs so rerunning the example starts cleanly.
  unlink(split_dir, recursive = TRUE)
  unlink(occ_dir, recursive = TRUE)
  unlink(range_dir, recursive = TRUE)

  # Split the input table into one occurrence file per speciesKey without
  # loading the full file into memory.
  split_summary <- split_gbif_by_species(
    input_file = gbif_file,
    outdir = split_dir,
    chunk_size = 10,
    sep_in = "\t",
    sep_out = "\t",
    overwrite = TRUE,
    verbose = FALSE
  )

  split_summary[, c("species_name", "n_records", "species_file")]

  # The batch step resolves "eco_terra" with read_ecoreg(), so it needs the
  # remote source to be reachable.
  if (gbif_have(read_ecoreg("eco_terra", save_dir = tempdir()))) {

  range_summary <- species_csvs_to_ranges(
    species_dir = split_dir,
    ecoreg = "eco_terra",
    ecoreg_name = "ECO_NAME",
    outdir = range_dir,
    occ_outdir = occ_dir,
    occ_save_as = "tsv",
    range_save_as = "rds",
    sep_in = "\t",
    overwrite = TRUE,
    degrees_outlier = 30,
    clust_pts_outlier = 2,
    buff_width_point = 1,
    buff_incrmt_pts_line = 0.1,
    buff_width_polygon = 1,
    format = "SpatVector",
    verbose = FALSE
  )

  range_summary[, c("species_name", "n_points", "range_file")]

  # Read the saved ranges back from disk and plot both species together.
  range_one <- read_range_rds(range_summary$range_file[1])
  range_two <- read_range_rds(range_summary$range_file[2])

  combined_ext <- terra::ext(
    min(terra::xmin(range_one$rangeOutput), terra::xmin(range_two$rangeOutput)),
    max(terra::xmax(range_one$rangeOutput), terra::xmax(range_two$rangeOutput)),
    min(terra::ymin(range_one$rangeOutput), terra::ymin(range_two$rangeOutput)),
    max(terra::ymax(range_one$rangeOutput), terra::ymax(range_two$rangeOutput))
  )

  terra::plot(combined_ext, col = NA, legend = FALSE)
  terra::plot(range_one$rangeOutput, col = grDevices::rgb(0.1, 0.6, 0.2, 0.5), add = TRUE)
  terra::plot(range_two$rangeOutput, col = grDevices::rgb(0.8, 0.3, 0.1, 0.5), add = TRUE)

  }
}

}
