# FlowAi API example (R 4.1+, httr2): a gauge's latest reading, its observations and forecast as CSV,
# and several gauges in one call through the PI-JSON feed.
#
#   install.packages(c("httr2", "jsonlite"))
#   Sys.setenv(FLOWAI_API_KEY = "fai_...")   # from Profile > Integrations; better in ~/.Renviron than in the script
#   source("flowai_example.R")

library(httr2)

api <- Sys.getenv("FLOWAI_API_URL", "https://api.flowai-forecast.com")
gauge_id <- "02KF019"                       # a WSC station id
gauge_ids <- c("02KF019", "02HB029")

# GET a FlowAi URL with the key; waits and retries when the key's rate limit (HTTP 429) is reached.
flowai_get <- function(path, query = list()) {
  request(api) |>
    req_url_path_append(path) |>
    req_url_query(!!!query, .multi = "explode") |>
    req_auth_bearer_token(Sys.getenv("FLOWAI_API_KEY")) |>
    req_retry(max_tries = 2, is_transient = \(resp) resp_status(resp) == 429) |>
    req_timeout(30) |>
    req_perform()
}

# 1. The gauge and its latest reading
gauge <- flowai_get(paste0("api/v1/gauges/", gauge_id)) |> resp_body_json()
latest <- flowai_get(paste0("api/v1/gauges/", gauge_id, "/latest")) |> resp_body_json()
cat(sprintf("%s (%s): %s m3/s at %s\n", gauge$name, gauge_id, latest$flow_cms, latest$flow_timestamp))

# 2. Daily observed flow and level, last 7 days, newest first, to CSV. Each row is the provider's daily value,
#    stamped with its calendar date (00:00). For real-time readings use /recent (the last 48 hours) or the feed (step 4).
#    A missing value (JSON null) becomes NA.
observed <- flowai_get(paste0("api/v1/gauges/", gauge_id, "/observed"), list(days = 7)) |>
  resp_body_json(simplifyVector = TRUE)
readings <- observed$readings[, c("timestamp", "flow_cms", "level_m", "flag")]
readings$timestamp <- substr(readings$timestamp, 1, 10)
names(readings)[1] <- "date"
write.csv(readings, paste0(gauge_id, "_observed.csv"), row.names = FALSE)
cat(nrow(readings), "days observed ->", paste0(gauge_id, "_observed.csv\n"))

# 3. The latest forecast, one row per day, to CSV
forecast <- flowai_get(paste0("api/v1/gauges/", gauge_id, "/forecast")) |> resp_body_json(simplifyVector = TRUE)
days <- subset(forecast$forecasts, segment == "forecast", select = c(valid_date, lead_days, flow_cms))
days <- cbind(issue_time_utc = forecast$issue_time, days)
write.csv(days, paste0(gauge_id, "_forecast.csv"), row.names = FALSE)
cat(sprintf("forecast issued %s: %d days -> %s_forecast.csv\n", forecast$issue_time, nrow(days), gauge_id))

# 4. Several gauges and series in one call: the PI-JSON feed
now <- Sys.time()
utc <- \(t) format(t, "%Y-%m-%dT%H:%M:%SZ", tz = "UTC")
feed <- flowai_get("rest/fewspiservice/v1/timeseries", list(
  locationIds = gauge_ids, parameterIds = c("Q.obs", "Q.fcst.day"),
  startTime = utc(now - 2 * 86400), endTime = utc(now + 11 * 86400), documentFormat = "PI_JSON"))
for (series in resp_body_json(feed)$timeSeries) {
  n <- length(series$events)
  last <- if (n > 0) with(series$events[[n]], paste(date, time, "=", value)) else "no values"
  cat(sprintf("%s %s: %d values, last %s\n", series$header$locationId, series$header$parameterId, n, last))
}
cat(resp_header(feed, "X-FlowAi-Disclaimer"), "\n")
