##############################################
  # dat1: Basic synthetic data with causal relationship
  set.seed(123)
  n1 <- 100
  t1 <- 1:n1
  dat1_ds1 <- sin(2 * pi * t1 / 10) + rnorm(n1, 0, 0.1)
  dat1_ds2 <- array(NA, dim = c(n1, 5, 4))
  for (i in 1:5) {
    for (j in 1:4) {
      dat1_ds2[, i, j] <- cos(2 * pi * t1 / 10) + rnorm(n1, 0, 0.1) + 0.1 * i + 0.05 * j
    }
  }

  # dat2: Strongly correlated data
  set.seed(42)
  n2 <- 100
  dat2_ds1 <- cumsum(rnorm(n2))
  dat2_ds2 <- array(NA, dim = c(n2, 3, 3))
  for (i in 1:3) {
    for (j in 1:3) {
      dat2_ds2[, i, j] <- 0.5 * dat2_ds1 + rnorm(n2, 0, 0.5) + 0.1 * (i + j)
    }
  }

  # dat3: Constant data (edge case)
  n3 <- 50
  dat3_ds1 <- rep(1, n3)
  dat3_ds2 <- array(2, dim = c(n3, 3, 2))

  # dat4: Data with different lengths for testing
  dat4_ds1 <- rnorm(50)
  dat4_ds2 <- array(rnorm(50 * 3 * 2), dim = c(50, 3, 2))

  # dat5: Data with NA values
  dat5_ds1 <- dat1_ds1
  dat5_ds2 <- dat1_ds2
  dat5_ds1[c(10, 20, 30)] <- NA
  dat5_ds2[c(15, 25, 35), , ] <- NA

##############################################
test_that("1. Input checks", {

  # ds1 parameter checks
  expect_error(
    Causality1D3D(c(), dat1_ds2),
    "Time dimensions of ds1 and ds2 must match"
  )

  # ds2 parameter checks
  expect_error(
    Causality1D3D(dat1_ds1, c(1:10)),
    "ds2 should be a 3D array"
  )
  expect_error(
    Causality1D3D(dat1_ds1, matrix(1:20, 10, 2)),
    "ds2 should be a 3D array"
  )

  # Dimension mismatch checks
  wrong_ds2 <- array(rnorm(50 * 5 * 4), dim = c(50, 5, 4))
  expect_error(
    Causality1D3D(dat1_ds1, wrong_ds2),
    "Time dimensions of ds1 and ds2 must match"
  )

  # sig parameter checks
  expect_error(
    Causality1D3D(dat1_ds1, dat1_ds2, sig = 85),
    "Only 90, 95 and 99 significance levels are supported"
  )
  expect_error(
    Causality1D3D(dat1_ds1, dat1_ds2, sig = 98),
    "Only 90, 95 and 99 significance levels are supported"
  )

})

##############################################
test_that("2. Output checks: dat1 basic functionality", {
  result1 <- Causality1D3D(dat1_ds1, dat1_ds2)

  expect_equal(
    names(result1),
    c("infflow", "infflow_sig")
  )
  expect_true(
    is.list(result1)
  )
  expect_equal(
    length(result1),
    2
  )
  expect_true(
    is.array(result1$infflow)
  )
  expect_true(
    is.array(result1$infflow_sig)
  )
  expect_equal(
    dim(result1$infflow),
    c(5, 4)
  )
  expect_equal(
    dim(result1$infflow_sig),
    c(5, 4)
  )
  expect_true(
    !is.null(attr(result1$infflow, "name"))
  )
  expect_true(
    !is.null(attr(result1$infflow_sig, "name"))
  )
  expect_true(
    grepl("not normalised", attr(result1$infflow, "name"))
  )

})

##############################################
test_that("3. Output checks: dat1 normalization", {
  result_norm <- Causality1D3D(dat1_ds1, dat1_ds2, normalise = TRUE)
  result_no_norm <- Causality1D3D(dat1_ds1, dat1_ds2, normalise = FALSE)

  expect_equal(
    names(result_norm),
    c("infflow", "infflow_sig")
  )
  expect_equal(
    dim(result_norm$infflow),
    c(5, 4)
  )
  expect_true(
    !identical(result_norm$infflow, result_no_norm$infflow)
  )
  expect_true(
    grepl("normalised", attr(result_norm$infflow, "name"))
  )
  expect_true(
    grepl("not normalised", attr(result_no_norm$infflow, "name"))
  )

  # Check that normalized values are finite where calculated
  finite_vals <- result_norm$infflow[is.finite(result_norm$infflow)]
  if (length(finite_vals) > 0) {
    expect_true(all(is.finite(finite_vals)))
  }

})

##############################################
test_that("4. Output checks: dat2 correlated data", {
  result2 <- Causality1D3D(dat2_ds1, dat2_ds2)

  expect_equal(
    names(result2),
    c("infflow", "infflow_sig")
  )
  expect_equal(
    dim(result2$infflow),
    c(3, 3)
  )
  expect_equal(
    dim(result2$infflow_sig),
    c(3, 3)
  )
  expect_true(
    is.array(result2$infflow)
  )
  expect_true(
    is.array(result2$infflow_sig)
  )

})

##############################################
test_that("5. Output checks: different significance levels", {
  for (sig_level in c(90, 95, 99)) {
    result_sig <- Causality1D3D(dat1_ds1, dat1_ds2, sig = sig_level)
    
    expect_equal(
      names(result_sig),
      c("infflow", "infflow_sig")
    )
    expect_equal(
      dim(result_sig$infflow),
      c(5, 4)
    )
    expect_equal(
      dim(result_sig$infflow_sig),
      c(5, 4)
    )
  }

})

##############################################
test_that("6. Output checks: dat3 constant data", {
  # Constant data should either work or fail gracefully
  result3 <- tryCatch(
    {
      Causality1D3D(dat3_ds1, dat3_ds2)
    },
    error = function(e) {
      return(NULL)
    }
  )

  if (!is.null(result3)) {
    expect_true(is.list(result3))
    expect_equal(length(result3), 2)
    expect_equal(dim(result3$infflow), c(3, 2))
  }

})

##############################################
test_that("7. Output checks: dat4 different lengths", {
  lengths <- c(50, 100, 200)
  
  for (len in lengths) {
    ds1_len <- rnorm(len)
    ds2_len <- array(rnorm(len * 3 * 2), dim = c(len, 3, 2))
    
    result_len <- Causality1D3D(ds1_len, ds2_len)
    
    expect_true(is.list(result_len))
    expect_equal(length(result_len), 2)
    expect_equal(dim(result_len$infflow), c(3, 2))
    expect_equal(dim(result_len$infflow_sig), c(3, 2))
  }

})

##############################################
test_that("8. Output checks: dat5 with NA values", {
  # Data with NAs should either work or fail gracefully
  result5 <- tryCatch(
    {
      Causality1D3D(dat5_ds1, dat5_ds2)
    },
    error = function(e) {
      return(NULL)
    }
  )

  if (!is.null(result5)) {
    expect_true(is.list(result5))
    expect_equal(length(result5), 2)
    expect_equal(dim(result5$infflow), c(5, 4))
  }

})

##############################################
test_that("9. Parameter variations", {
  # Test different dt values
  result_dt1 <- Causality1D3D(dat1_ds1, dat1_ds2, dt = 1)
  result_dt2 <- Causality1D3D(dat1_ds1, dat1_ds2, dt = 2)

  expect_equal(names(result_dt1), names(result_dt2))
  expect_equal(dim(result_dt1$infflow), dim(result_dt2$infflow))

  # Test combination of parameters
  result_combo <- Causality1D3D(dat1_ds1, dat1_ds2, dt = 1, normalise = TRUE, sig = 99)
  
  expect_equal(
    names(result_combo),
    c("infflow", "infflow_sig")
  )
  expect_true(
    grepl("normalised", attr(result_combo$infflow, "name"))
  )

})