# Helper functions for setting up test data fixtures

#' Setup a temporary data directory with bundled fixtures
#'
#' This function creates a temporary directory and populates it with
#' the bundled test fixtures (metadata, zones, OD data) to mimic
#' a populated cache directory.
#'
#' @return The path to the temporary directory
setup_test_data_dir <- function() {
  test_dir <- tempfile("spod_test_")
  dir.create(test_dir, recursive = TRUE)

  fixture_path <- system.file("testdata", package = "spanishoddata")
  if (fixture_path == "") {
    # Fallback for when running interactively without package load?
    fixture_path <- testthat::test_path("../../inst/testdata")
  }

  if (!dir.exists(fixture_path)) {
    # Try another fallback for R CMD check where inst/ is gone
    fixture_path <- testthat::test_path("../..", "testdata")
  }

  if (!dir.exists(fixture_path)) {
    stop("Could not find test fixtures at: ", fixture_path)
  }

  # 1. Setup Metadata Cache
  # -----------------------
  # Copy mock metadata to expected cache location so spod_available_data finds it
  meta_cache <- file.path(test_dir, spod_subfolder_metadata_cache())
  dir.create(meta_cache, recursive = TRUE)

  # The cache logic looks for pattern: metadata_s3_v{ver}_YYYY-MM-DD.rds
  # We copy our mock file to a name that guarantees it's picked up as "latest"
  mock_meta_v2 <- file.path(
    fixture_path,
    "metadata/available_data_s3_v2_mock.rds"
  )
  if (file.exists(mock_meta_v2)) {
    # Use a future date to ensure it's NEVER considered stale by spod_available_data_s3
    target_name <- paste0("metadata_s3_v2_", Sys.Date() + 30, ".rds")
    if (!file.copy(mock_meta_v2, file.path(meta_cache, target_name))) {
      stop("Failed to copy v2 mock metadata")
    }
  }

  mock_meta_v1 <- file.path(
    fixture_path,
    "metadata/available_data_s3_v1_mock.rds"
  )
  if (file.exists(mock_meta_v1)) {
    target_name <- paste0("metadata_s3_v1_", Sys.Date() + 30, ".rds")
    if (!file.copy(mock_meta_v1, file.path(meta_cache, target_name))) {
      stop("Failed to copy v1 mock metadata")
    }
  }

  # 2. Setup Zone Cache
  # -------------------
  # spod_get_zones checks 'clean_data/v{ver}/zones'
  clean_zones <- file.path(test_dir, "clean_data/v2/zones")
  dir.create(clean_zones, recursive = TRUE)

  # Copy all bundled zone GPKGs
  zone_fixtures <- list.files(
    file.path(fixture_path, "clean_data/v2/zones"),
    full.names = TRUE
  )
  if (length(zone_fixtures) > 0) {
    if (!all(file.copy(zone_fixtures, clean_zones))) {
      stop("Failed to copy zone fixtures")
    }
  }

  # 3. Setup Raw OD Data
  # --------------------
  # spod_duckdb_od expects 'raw_data_cache/v{ver}/estudios_basicos/por-distritos/viajes/ficheros-diarios/'
  # and 'raw_data_cache/v{ver}/distritos/viajes/ficheros-diarios/'

  # Recreate Hive structure
  raw_od_hive <- file.path(
    test_dir,
    "raw_data_cache/v2/estudios_basicos/por-distritos/viajes/ficheros-diarios/year=2022/month=2/day=1"
  )
  dir.create(raw_od_hive, recursive = TRUE)
  hive_src <- file.path(fixture_path, "raw_data/v2/od_hive_data.csv.gz")
  if (!file.exists(hive_src)) {
    stop("Hive OD fixture missing at: ", hive_src)
  }
  if (!file.copy(hive_src, file.path(raw_od_hive, "data.csv.gz"))) {
    stop("Failed to copy Hive OD fixture")
  }

  # Recreate standard daily structure
  raw_od_day <- file.path(
    test_dir,
    "raw_data_cache/v2/distritos/viajes/ficheros-diarios"
  )
  dir.create(raw_od_day, recursive = TRUE)
  day_src <- file.path(fixture_path, "raw_data/v2/od_dist_day.csv.gz")
  if (!file.exists(day_src)) {
    stop("Daily OD fixture missing at: ", day_src)
  }
  if (
    !file.copy(
      day_src,
      file.path(raw_od_day, "viajes_distrito_2022-02-01.csv.gz")
    )
  ) {
    stop("Failed to copy daily OD fixture")
  }

  return(test_dir)
}

#' Context manager for mocked downloads
#'
#' Prevents actual downloads during tests.
#'
#' @param code The code to run
local_mock_download <- function(env = parent.frame()) {
  # Mock spod_download to do nothing (files are already in test_dir)
  testthat::local_mocked_bindings(
    spod_download = function(...) invisible(NULL),
    .package = "spanishoddata",
    .env = env
  )
}

#' Setup a temporary directory with a sample parquet file
#'
#' Creates a parquet file using arrow (if available) or duckdb
#' to test spod_connect with parquet folders.
#'
#' @return Path to the parquet folder
setup_parquet_dir <- function() {
  parquet_dir <- tempfile("spod_parquet_")
  dir.create(parquet_dir)

  # Create a simple data frame
  df <- data.frame(
    id = 1:10,
    val = letters[1:10]
  )

  parquet_file <- file.path(parquet_dir, "test.parquet")

  # Try using arrow if installed, otherwise skip (or fail if this is essential)
  # But for testing `spod_connect` which connects to parquet, we need a parquet file.
  # We can use duckdb to write it since we depend on duckdb.

  con <- DBI::dbConnect(duckdb::duckdb())
  on.exit(DBI::dbDisconnect(con, shutdown = TRUE))

  DBI::dbWriteTable(con, "temp_df", df)
  DBI::dbExecute(
    con,
    paste0("COPY temp_df TO '", parquet_file, "' (FORMAT PARQUET)")
  )

  return(parquet_dir)
}

#' Setup a temporary duckdb database file
#'
#' @return Path to the .duckdb file
setup_duckdb_file <- function() {
  db_file <- tempfile("spod_db_", fileext = ".duckdb")
  con <- DBI::dbConnect(duckdb::duckdb(), dbdir = db_file)

  df <- data.frame(id = 1:5, val = LETTERS[1:5])
  DBI::dbWriteTable(con, "my_table", df)

  DBI::dbDisconnect(con, shutdown = TRUE)
  return(db_file)
}
