test_that("model_out_tbl_1 output is valid", {
  model_out_tbl_1 <- utils::read.csv(test_path(
    "testdata/model_out_tbl_quantile_1.csv"
  ))
  oracle_output_1 <- utils::read.csv(test_path("testdata/target_data_1.csv")) |>
    dplyr::rename(oracle_value = observation)
  act_forecast <- transform_quantile_model_out(
    model_out_tbl = model_out_tbl_1,
    oracle_output = oracle_output_1
  )

  exp_forecast <- utils::read.csv(test_path("testdata/exp_forecast_2.csv"))
  class(exp_forecast) <- c(
    "forecast_quantile",
    "forecast",
    "data.table",
    "data.frame"
  )
  expect_equal(act_forecast, exp_forecast)
})


test_that("model_out_tbl_1 columns are valid", {
  model_out_tbl_1 <- utils::read.csv(
    test_path("testdata/model_out_tbl_quantile_1.csv")
  ) |>
    dplyr::rename(loc = location, trgt = target, date = target_end_date)

  oracle_output_1 <- utils::read.csv(
    test_path("testdata/target_data_1.csv")
  ) |>
    dplyr::rename(
      loc = location,
      date = target_end_date,
      oracle_value = observation
    )
  act_forecast <- transform_quantile_model_out(
    model_out_tbl = model_out_tbl_1,
    oracle_output = oracle_output_1
  )
  exp_forecast <- utils::read.csv(
    test_path("testdata/exp_forecast_2.csv")
  ) |>
    dplyr::rename(loc = location, trgt = target, date = target_end_date)
  class(exp_forecast) <- c(
    "forecast_quantile",
    "forecast",
    "data.table",
    "data.frame"
  )
  expect_equal(act_forecast, exp_forecast, ignore_attr = "class")
})

test_that("model_out_tbl_1 has any rows", {
  # Error is thrown by scoringutils::assert_forecast_generic()
  model_out_tbl_1 <- utils::read.csv(
    test_path("testdata/model_out_tbl_quantile_1.csv")
  )
  oracle_output_1 <- utils::read.csv(
    test_path("testdata/target_data_1.csv")
  ) |>
    dplyr::rename(oracle_value = observation)
  expect_error(
    suppressWarnings(transform_quantile_model_out(
      model_out_tbl = model_out_tbl_1[0, ],
      oracle_output = oracle_output_1
    )),
    regexp = "Must have at least 1 rows, but has 0 rows."
  )
})


test_that("many-to-one relationship exists between model_out_tbl and oracle_output", {
  model_out_tbl_1 <- utils::read.csv(
    test_path("testdata/model_out_tbl_quantile_1.csv")
  )
  oracle_output_2 <- utils::read.csv(
    test_path("testdata/target_data_2.csv")
  ) |>
    dplyr::rename(oracle_value = observation)

  expect_error(
    suppressMessages(transform_quantile_model_out(
      model_out_tbl = model_out_tbl_1,
      oracle_output = oracle_output_2
    )),
    regexp = "Each row in `x` must match at most 1 row in `y`."
  )
})

test_that("hubExamples data set is transformed correctly", {
  skip_if_not_installed("hubExamples")
  # Forecast data from hubExamples: <https://hubverse-org.github.io/hubExamples/reference/forecast_data.html>
  forecast_outputs <- hubExamples::forecast_outputs
  forecast_oracle_output <- hubExamples::forecast_oracle_output

  act_forecast <- transform_quantile_model_out(
    model_out_tbl = forecast_outputs,
    oracle_output = forecast_oracle_output
  )

  exp_forecast <- forecast_outputs |>
    dplyr::filter(output_type == "quantile") |>
    dplyr::rename(model = model_id, quantile_level = output_type_id) |>
    dplyr::mutate(quantile_level = as.numeric(quantile_level))
  expect_s3_class(
    act_forecast,
    c("forecast_quantile", "forecast", "data.table", "data.frame")
  )

  # same number of row as quantile predictions from model_out_tbl,
  # same predicted values
  expect_equal(nrow(exp_forecast), nrow(act_forecast))
  exp_act_forecast <- dplyr::full_join(
    exp_forecast,
    act_forecast,
    by = c(
      "model",
      "reference_date",
      "target",
      "horizon",
      "location",
      "target_end_date",
      "quantile_level"
    )
  )
  expect_equal(exp_act_forecast$predicted, exp_act_forecast$value)

  # correct observed values, in alignment with oracle_output
  exp_act_forecast <- dplyr::left_join(
    act_forecast,
    forecast_oracle_output |>
      dplyr::filter(output_type == "quantile") |>
      dplyr::rename(quantile_level = output_type_id) |>
      dplyr::mutate(quantile_level = as.numeric(quantile_level)),
    by = c("target", "location", "target_end_date")
  )
  expect_equal(exp_act_forecast$observed, exp_act_forecast$oracle_value)
})

test_that("oracle_output without output_type but with output_type_id works (#73)", {
  skip_if_not_installed("hubExamples")
  forecast_outputs <- hubExamples::forecast_outputs
  oracle_no_output_type <- hubExamples::forecast_oracle_output |>
    dplyr::filter(output_type == "quantile") |>
    dplyr::select(-"output_type")

  act_forecast <- transform_quantile_model_out(
    model_out_tbl = forecast_outputs,
    oracle_output = oracle_no_output_type
  )

  expect_s3_class(
    act_forecast,
    c("forecast_quantile", "forecast", "data.table", "data.frame")
  )

  # cross-check against the regular pathway (oracle keeps both columns)
  exp_forecast <- transform_quantile_model_out(
    model_out_tbl = forecast_outputs,
    oracle_output = hubExamples::forecast_oracle_output
  )
  expect_equal(act_forecast, exp_forecast)
})
