context("General functions")

test_that("General USGS retrievals working", {
  testthat::skip_on_cran()
  testthat::skip_on_ci()

  cql <- '{
  "op": "and",
  "args": [
    {
      "op": "in",
      "args": [
        { "property": "parameter_code" },
        [ "00060", "00065" ]
      ]
    },
   {
      "op": "in",
      "args": [
        { "property": "monitoring_location_id" },
        [ "USGS-07367300", "USGS-03277200" ]
      ]
    }
  ]
  }'

  dv_data <- read_waterdata(
    service = "daily",
    CQL = cql,
    time = c("2023-01-01", "2024-01-01")
  )

  expect_equal(as.Date(c("2023-01-01", "2024-01-01")), range(dv_data$time))
  expect_true(all(
    unique(dv_data$monitoring_location_id) %in%
      c("USGS-07367300", "USGS-03277200")
  ))

  cql_not_active <- '{
  "op": "and",
  "args": [
    {
      "op": "in",
      "args": [
        { "property": "parameter_code" },
        [ "00060", "00065" ]
      ]
    },
   {
      "op": "in",
      "args": [
        { "property": "monitoring_location_id" },
        [ "USGS-05212700"]
      ]
    }
  ]
  }'

  notActiveUSGS <- read_waterdata(
    CQL = cql_not_active,
    service = "daily",
    time = c("2014-01-01", "2014-01-07")
  )
  expect_true(nrow(notActiveUSGS) == 0)
})

test_that("General NWIS retrievals working", {
  testthat::skip_on_cran()
  testthat::skip_on_ci()

  multiSite <- read_waterdata_continuous(
    monitoring_location_id = c("USGS-04025500", "USGS-040263491"),
    parameter_code = "00060",
    time = c("2020-11-01", "2020-11-02")
  )

  expect_is(multiSite$time, "POSIXct")

  expect_error(readNWISdata(), "No arguments supplied")
  expect_error(readNWISdata(siteNumber = NA), "NA's are not allowed in query")

  bBox_inventory <- read_waterdata_ts_meta(
    bbox = c(-83, 38, -82.5, 38.5),
    parameter_code = "00010"
  )

  expect_true(length(unique(bBox_inventory$monitoring_location_id)) > 1)

  siteInfo <- read_waterdata_monitoring_location(state_name = "Wisconsin")

  timeseriesInfo <- read_waterdata_ts_meta(
    bbox = sf::st_bbox(siteInfo),
    parameter_code = "00010",
    computation_period_identifier = "Points"
  )

  expect_is(timeseriesInfo$begin, "POSIXct")

  # nolint start: line_length_linter

  # Test list:
  args <- list(
    monitoring_location_id = "USGS-05114000",
    parameter_code = "00060",
    time = c("2014-05-01T00:00Z", "2014-05-01T12:00Z")
  )

  instData <- do.call(read_waterdata_continuous, args)

  args2 <- list(
    monitoring_location_id = "USGS-05114000",
    parameter_code = "00060",
    time = c("2014-05-01", "2014-05-01")
  )

  daily_USGS <- do.call(read_waterdata_daily, args2)
  expect_lt(nrow(daily_USGS), nrow(instData))

  ohio <- read_waterdata_monitoring_location(
    state_name = "Ohio",
    site_type_code = "ST"
  )
  bbox <- sf::st_bbox(ohio)
  what_sites <- read_waterdata_ts_meta(parameter_code = "00665", bbox = bbox)
  expect_true(all(
    c("monitoring_location_id", "begin", "end", "parameter_name") %in%
      names(what_sites)
  ))

  huc <- read_waterdata_monitoring_location(hydrologic_unit_code = "02080202")
  expect_true(nrow(huc) > 0)

  # Test counties:

  county_code_stafford <- countyCdLookup(
    state = "Virginia",
    county = "Stafford",
    outputType = "id"
  )
  state_code_va <- stateCdLookup(input = "Virginia", outputType = "id")
  stafford <- read_waterdata_monitoring_location(
    county_code = county_code_stafford,
    state_code = state_code_va
  )
  stafford_bbox <- sf::st_bbox(stafford)

  dailyStaffordVA <- read_waterdata_daily(
    bbox = stafford_bbox,
    parameter_code = "00060",
    time = c("2015-01-01", "2015-01-30")
  )
  expect_gt(nrow(dailyStaffordVA), 1)

  # America Samoa?
  AS <- read_waterdata_monitoring_location(state_name = "American Samoa")
  expect_gt(nrow(AS), 0)

  site_id <- "USGS-01594440"
  rating_curve <- read_waterdata_ratings(
    monitoring_location_id = site_id,
    file_type = "base"
  )

  expect_equal(names(rating_curve), "USGS-01594440.base.rdb")

  state_rating_list <- read_waterdata_ratings(
    datetime = c(Sys.Date() - 1, NA),
    download_and_parse = FALSE
  )

  expect_true(length(state_rating_list) > 0)

  multi_hucs <- c("07130007", "07130011")
  multi_huc_sites <- read_waterdata_monitoring_location(
    hydrologic_unit_code = multi_hucs
  )

  multi_huc <- read_waterdata_daily(
    bbox = sf::st_bbox(multi_huc_sites),
    parameter_code = "63680",
    statistic_id = "00003",
    time = c("2015-06-18", "2015-06-18")
  )
  expect_equal(4, length(unique(multi_huc$monitoring_location_id)))

  peak_data <- readNWISdata(
    service = "peak",
    state_cd = "PA"
  )
  expect_lt(nrow(peak_data), 100000)

  peak_data <- readNWISdata(
    service = "peak",
    huc2_cd = "20"
  )
  expect_lt(nrow(peak_data), 100000)
})

test_that("read_waterdata_ts_meta", {
  testthat::skip_on_cran()
  testthat::skip_on_ci()
  # no service specified:
  availableData <- read_waterdata_ts_meta(
    monitoring_location_id = "USGS-05114000"
  )
  expect_gte(ncol(availableData), 18)

  uvData <- read_waterdata_ts_meta(
    monitoring_location_id = "USGS-05114000",
    computation_period_identifier = c("Points")
  )
  expect_equal(unique(uvData$computation_period_identifier), "Points")

  # multiple services
  uvDataMulti <- read_waterdata_ts_meta(
    monitoring_location_id = c("USGS-05114000", "USGS-09423350"),
    computation_period_identifier = c("Daily", "Points")
  )

  expect_true(all(
    unique(uvDataMulti$computation_period_identifier) %in% c("Daily", "Points")
  ))

  # state codes:
  wi_sites <- read_waterdata_monitoring_location(state_name = "Wisconsin")
  flow_and_temp <- read_waterdata_ts_meta(
    bbox = sf::st_bbox(wi_sites),
    parameter_code = c("00060", "00010"),
    statistic_id = "00003",
    computation_period_identifier = c("Daily", "Points")
  )

  expect_true(all(
    unique(flow_and_temp$computation_period_identifier) %in%
      c("Daily", "Points")
  ))
  expect_true(all(
    unique(flow_and_temp$parameter_code) %in% c("00060", "00010")
  ))
  expect_true(all(unique(flow_and_temp$statistic_id) %in% c("00003")))
})

test_that("General WQP retrievals working", {
  testthat::skip_on_cran()
  testthat::skip_on_ci()
  # nameToUse <- "pH"
  # pHData <- readWQPdata(
  #   siteid = "USGS-04024315",
  #   characteristicName = nameToUse,
  #   service = "ResultWQX3"
  # )
  # expect_is(pHData$Activity_StartDateTime, "POSIXct")
  # expect_type(pHData$USGSpcode, "character")
  # expect_type(pHData$Result_Measure, "double")
  # expect_type(pHData$SampleCollectionMethod_Identifier, "character")
  #
  # # testing lists:
  startDate <- as.Date("2022-01-01")
  secchi.names <- c(
    "Depth, Secchi disk depth",
    "Secchi depth",
    "Water transparency, Secchi disc",
    "Depth, Secchi disk depth (choice list)"
  )
  # "Transparency, Secchi tube with disk",
  # "Secchi Reading Condition (choice list)",
  # "Depth, Secchi disk visible at bottom (Y/N) (choice list)")

  args_2 <- list(
    "startDateLo" = startDate,
    "startDateHi" = "2024-01-01",
    statecode = "WI",
    characteristicName = secchi.names
  )

  # # Testing multiple lists:
  arg_3 <- list(
    "startDateLo" = startDate,
    "startDateHi" = "2023-12-31"
  )
  arg_4 <- list(
    statecode = "WI",
    characteristicName = secchi.names
  )

  # wqp.summary_no_atts <- readWQPdata(
  #   siteid = "USGS-04024315",
  #   characteristicName = nameToUse,
  #   ignore_attributes = TRUE,
  #   service = "ResultWQX3"
  # )
  # expect_true(
  #   !all(
  #     c("siteInfo", "variableInfo") %in% names(attributes(wqp.summary_no_atts))
  #   )
  # )
  #
  # rawPcode <- readWQPqw("USGS-01594440", "01075", "", "", legacy = FALSE)
  # expect_true(all(
  #   c("url", "queryTime", "siteInfo") %in%
  #     names(attributes(rawPcode))
  # ))
  #
  # # This means wqp_check_status was called:
  # expect_true("dataProviders" %in% names(attr(rawPcode, "headerInfo")))
  #
  # rawPcode2 <- readWQPqw(
  #   "USGS-01594440",
  #   "01075",
  #   "",
  #   "",
  #   ignore_attributes = TRUE
  # )
  # expect_true(all(
  #   !c("queryTime", "siteInfo") %in%
  #     names(attributes(rawPcode2))
  # ))
  #
  # # This means wqp_check_status wasn't called:
  # expect_false("dataProviders" %in% names(attr(rawPcode2, "headerInfo")))
  #
  # pHData <- readWQPdata(
  #   siteid = "USGS-04024315",
  #   characteristicName = "pH",
  #   service = "ResultWQX3"
  # )
  # expect_true(all(
  #   c("url", "queryTime", "siteInfo", "headerInfo") %in%
  #     names(attributes(pHData))
  # ))
  #
  # # # This means wqp_check_status was called:
  # expect_true("dataProviders" %in% names(attr(pHData, "headerInfo")))
  #
  # pHData2 <- readWQPdata(
  #   siteid = "USGS-04024315",
  #   characteristicName = "pH",
  #   ignore_attributes = TRUE,
  #   service = "ResultWQX3"
  # )
  # expect_true(all(
  #   !c("queryTime", "siteInfo") %in%
  #     names(attributes(pHData2))
  # ))
  #
  # # # This means wqp_check_status was called:
  # expect_false("dataProviders" %in% names(attr(pHData2, "headerInfo")))
  #
  # rawPcode <- readWQPqw(
  #   "USGS-01594440",
  #   "01075",
  #   ignore_attributes = TRUE,
  #   legacy = FALSE
  # )
  # headerInfo <- attr(rawPcode, "headerInfo")
  # wqp_request_id <- headerInfo$`wqp-request-id`
  # count_info <- wqp_check_status(wqp_request_id)
  #
  # expect_true("dataProviders" %in% names(count_info))
})


test_that("zeroPad handles NAs", {
  toPad <- c(1, 5, 55, NA)
  padded <- zeroPad(toPad, 3)
  expect_true(identical(c("001", "005", "055", NA), padded))
})

test_that("Dates with no days can be handled", {
  testthat::skip_on_cran()
  testthat::skip_on_ci()

  empty_df <- read_waterdata_field_measurements(
    monitoring_location_id = "USGS-425957088141001",
    time = c("1980-01-01", NA)
  )
  expect_true(nrow(empty_df) > 0)
})

context("whatWQPsamples")
test_that("whatWQPsamples working", {
  testthat::skip_on_cran()
  testthat::skip_on_ci()
  # The warning is caused by a confirmed bug in WQP
  siteInfo <- whatWQPsamples(siteid = "USGS-01594440")
  expect_true(nrow(siteInfo) > 0)
})

context("whatWQPmetrics")
test_that("whatWQPmetrics working", {
  testthat::skip_on_cran()
  testthat::skip_on_ci()
  type <- "Stream"
  siteInfo <- whatWQPmetrics(countycode = "US:55:025", siteType = type)
  expect_true(ncol(siteInfo) >= 21)
})

context("whatWQPdata")
test_that("whatWQPdata working", {
  testthat::skip_on_cran()
  testthat::skip_on_ci()

  site1 <- whatWQPdata(siteid = "USGS-01594440")
  expect_is(site1, "data.frame")
  expect_equal(1, nrow(site1))

  type <- "Stream"
  sites <- whatWQPdata(countycode = "US:55:025", siteType = type)
  expect_gt(nrow(sites), 1)

  lakeSites <- whatWQPdata(
    siteType = "Lake, Reservoir, Impoundment",
    statecode = "US:55"
  )
  expect_is(lakeSites$activityCount, "numeric")
})

context("read_waterdata_ts_meta")
test_that("read_waterdata_ts_meta working", {
  testthat::skip_on_cran()
  testthat::skip_on_ci()

  siteListOhio <- read_waterdata_monitoring_location(state_name = "Ohio")
  siteListPhos <- read_waterdata_ts_meta(
    bbox = sf::st_bbox(siteListOhio),
    parameter_code = "00665"
  )
  expect_true(nrow(siteListPhos) > 0)
  expect_is(siteListPhos$begin, "POSIXct")

  bboxSites <- read_waterdata_ts_meta(
    bbox = c(-92.5, 45.4, -87, 47),
    parameter_code = "00060"
  )
  expect_true(nrow(bboxSites) > 0)
})

context("readWQPdots")
test_that("readWQPdots working", {
  testthat::skip_on_cran()

  # bbox vector turned into single string with coords separated by semicolons
  formArgs_bbox <- dataRetrieval:::readWQPdots(bbox = c(-92.5, 45.4, -87, 47))
  expect_true(length(formArgs_bbox) == 2)
  expect_true(length(formArgs_bbox$values$bBox) == 1)

  # NWIS names (siteNumber) converted to WQP expected names (siteid)
  formArgs_site <- dataRetrieval:::readWQPdots(siteNumber = "04010301")
  expect_true(length(formArgs_site) == 2)
  expect_true("siteid" %in% names(formArgs_site$values))
  expect_false("siteNumber" %in% names(formArgs_site$values))

  # NWIS names (stateCd) converted to WQP expected names (statecode)
  formArgs <- dataRetrieval:::readWQPdots(stateCd = "OH", parameterCd = "00665")
  expect_true(length(formArgs$values) == 4)
  expect_true("statecode" %in% names(formArgs$values))
  expect_false("stateCd" %in% names(formArgs$values))

  bbox <- c(-86.97361, 34.48827, -86.61349, 34.65623)
  what_bbox <- whatWQPdata(bBox = bbox)
  expect_true(nrow(what_bbox) > 0)
  x <- whatWQPsites(bBox = bbox)
  expect_true(nrow(x) > 0)
  df <- readWQPdata(
    bBox = bbox,
    characteristicName = "Total Coliform",
    startDateLo = "2023-01-01",
    startDateHi = "2023-12-31",
    service = "Result",
    dataProfile = "narrowResult"
  )
  expect_true(nrow(df) > 0)
  df_legacy <- readWQPdata(
    bBox = bbox,
    characteristicName = "Total Coliform",
    startDateLo = "2023-01-01",
    startDateHi = "2023-12-31",
    service = "Result",
    dataProfile = "narrowResult"
  )
  expect_true(nrow(df_legacy) > 0)
})


test_that("internal functions", {
  # get empty_col type
  expect_equal(dataRetrieval:::empty_col("numeric"), numeric())
  expect_equal(dataRetrieval:::empty_col("character"), character())
  expect_equal(
    dataRetrieval:::empty_col("Date"),
    as.Date(numeric(), origin = "1970-01-01")
  )

  # add empty columns
  df1 <- data.frame(
    a = 1:2,
    b = c("a", "b"),
    c = as.Date(c("2010-01-01", "2010-01-02")),
    stringsAsFactors = FALSE
  )
  df2 <- data.frame(
    d = 1:2,
    b = c("a", "b"),
    e = factor(c("c", "d")),
    stringsAsFactors = FALSE
  )

  df2_ret <- dataRetrieval:::add_empty_col(df2, df1, c("a", "c"))
  df1_ret <- dataRetrieval:::add_empty_col(df1, df2, c("d", "e"))

  expect_true(ncol(df2_ret) == 5)
  expect_true(ncol(df1_ret) == 5)
  expect_true(all(is.na(df2_ret[, c("a", "c")])))
  expect_true(all(is.na(df1_ret[, c("d", "e")])))

  bound_df <- dataRetrieval:::r_bind_dr(df1, df2)

  expect_true(nrow(bound_df) == 4)
  expect_true(class(bound_df$c) == "Date")
  expect_true(class(bound_df$a) == "integer")
  expect_true(class(bound_df$b) == "character")
})


test_that("importWQP convertType", {
  testthat::skip_on_cran()

  SC <- readWQPqw(
    siteNumbers = "USGS-05288705",
    parameterCd = "00300",
    convertType = TRUE,
    legacy = TRUE
  )
  expect_in("ActivityStartDateTime", names(SC))

  SC2 <- readWQPqw(
    siteNumbers = "USGS-05288705",
    parameterCd = "00300",
    convertType = FALSE,
    legacy = TRUE
  )
  expect_true(!"ActivityStartDateTime" %in% names(SC2))

  lakeSites_chars <- whatWQPdata(
    siteType = "Lake, Reservoir, Impoundment",
    statecode = "US:55",
    convertType = FALSE
  )
  expect_is(lakeSites_chars$lat, "character")
})

test_that("format_dates", {
  start_end <- c("2021-01-01", "2022-01-01")
  expect_equal(
    dataRetrieval:::format_api_dates(start_end, date = TRUE),
    "2021-01-01/2022-01-01"
  )
  expect_equal(
    dataRetrieval:::format_api_dates(start_end, date = FALSE),
    "2021-01-01T00:00:00Z/2022-01-01T00:00:00Z"
  )

  start_end <- c("", "")
  expect_equal(dataRetrieval:::format_api_dates(start_end), NA)

  period <- "P7D"

  expect_equal(dataRetrieval:::format_api_dates(period), "P7D")

  start <- c("2021-01-01", NA)

  expect_equal(
    dataRetrieval:::format_api_dates(start),
    "2021-01-01T00:00:00Z/.."
  )
  expect_equal(dataRetrieval:::format_api_dates(start, TRUE), "2021-01-01/..")

  end <- c(NA, "2021-01-01")

  expect_equal(dataRetrieval:::format_api_dates(end), "../2021-01-01T00:00:00Z")
  expect_equal(dataRetrieval:::format_api_dates(end, TRUE), "../2021-01-01")
  #
  # Bad test because it assumes a local timezone
  # This worked locally, but failed on a CI job
  # # end <- c(NA, as.POSIXct("2021-01-01 12:15:00"))
  # # expect_equal(dataRetrieval:::format_api_dates(end),
  # #              "../2021-01-01T18:15:00Z")
  #
  # start_end <- as.POSIXct(c("2021-01-01 12:15:00",
  #                           "2022-01-01 16:45"))
  # expect_equal(dataRetrieval:::format_api_dates(start_end),
  #              "2021-01-01T18:15:00Z/2022-01-01T22:45:00Z")

  start_end <- as.POSIXct(
    c("2021-01-01 12:15:00", "2022-01-01 16:45"),
    tz = "America/New_York"
  )

  expect_equal(
    dataRetrieval:::format_api_dates(start_end),
    "2021-01-01T17:15:00Z/2022-01-01T21:45:00Z"
  )

  # If you don't specify a timezone, it will assume UTC
  start_end2 <- c("2021-01-01 12:15:00", "")
  expect_equal(
    dataRetrieval:::format_api_dates(start_end2),
    "2021-01-01T12:15:00Z/.."
  )

  # If you do specify a timezone, it should maintain it, but convert to UTC:
  start_end2 <- c("2021-01-01T12:15:00-0500", "")
  expect_equal(
    dataRetrieval:::format_api_dates(start_end2),
    "2021-01-01T17:15:00Z/.."
  )

  time = c("2014-05-01T00:00:00Z", "2014-05-01T12:00:00Z")
  expect_equal(
    dataRetrieval:::format_api_dates(time),
    "2014-05-01T00:00:00Z/2014-05-01T12:00:00Z"
  )

  time = c("2014-05-01T00:00Z", "2014-05-01T12:00Z")
  expect_equal(
    dataRetrieval:::format_api_dates(time),
    "2014-05-01T00:00:00Z/2014-05-01T12:00:00Z"
  )

  expect_equal(
    dataRetrieval:::format_api_dates(c("2010-01-01T00:00Z", NA)),
    "2010-01-01T00:00:00Z/.."
  )

  expect_equal(
    dataRetrieval:::format_api_dates(c(
      "2010-01-01T00:00Z",
      "2010-01-01T05:00Z"
    )),
    "2010-01-01T00:00:00Z/2010-01-01T05:00:00Z"
  )

  start <- "2025-10-01"
  end <- as.Date("2026-02-02")

  expect_equal(
    dataRetrieval:::format_api_dates(c(start, end), date = TRUE),
    "2025-10-01/2026-02-02"
  )
})
