# Shared test fixtures for flexhaz tests
#
# These helper functions are automatically loaded by testthat before running
# any tests. They provide common DFR distribution fixtures used across
# multiple test files.

# =============================================================================
# Distribution Fixtures
# =============================================================================

#' Create exponential DFR distribution for testing
#'
#' Exponential has constant hazard h(t) = lambda, H(t) = lambda * t
#'
#' @param lambda Optional rate parameter. If NULL, no default parameter.
#' @return A dfr_dist object
make_exponential_dfr <- function(lambda = NULL) {
  dfr_dist(
    rate = function(t, par, ...) {
      rep(par[1], length(t))  # constant hazard = lambda
    },
    par = lambda
  )
}

#' Create Weibull DFR distribution for testing
#'
#' Weibull has hazard h(t) = (k/sigma) * (t/sigma)^(k-1)
#' Cumulative hazard H(t) = (t/sigma)^k
#'
#' @param shape Optional shape parameter k
#' @param scale Optional scale parameter sigma
#' @return A dfr_dist object
make_weibull_dfr <- function(shape = NULL, scale = NULL) {
  par <- if (!is.null(shape) && !is.null(scale)) c(shape, scale) else NULL
  dfr_dist(
    rate = function(t, par, ...) {
      k <- par[1]      # shape
      sigma <- par[2]  # scale
      (k / sigma) * (t / sigma)^(k - 1)
    },
    par = par
  )
}

# =============================================================================
# Data Frame Fixtures
# =============================================================================

#' Create test data frame for exact observations
#'
#' @param times Vector of observation times
#' @return Data frame with t and delta columns
make_exact_data <- function(times) {
  data.frame(
    t = times,
    delta = rep(1, length(times))  # 1 = exact observation
  )
}

#' Create test data frame for right-censored observations
#'
#' @param times Vector of censoring times
#' @return Data frame with t and delta columns
make_censored_data <- function(times) {
  data.frame(
    t = times,
    delta = rep(0, length(times))  # 0 = right-censored
  )
}

#' Create mixed data (exact + censored)
#'
#' @param exact_times Vector of exact observation times
#' @param censored_times Vector of censoring times
#' @return Data frame with t and delta columns
make_mixed_data <- function(exact_times, censored_times) {
  rbind(
    make_exact_data(exact_times),
    make_censored_data(censored_times)
  )
}

# =============================================================================
# Analytical Functions for Verification
# =============================================================================

#' Analytical exponential log-likelihood for exact observations
#' loglik = sum(log(lambda) - lambda * t_i) = n * log(lambda) - lambda * sum(t)
exp_loglik_exact <- function(times, lambda) {
  n <- length(times)
  n * log(lambda) - lambda * sum(times)
}

#' Analytical exponential log-likelihood for right-censored observations
#' loglik = sum(-lambda * t_i) = -lambda * sum(t)
exp_loglik_censored <- function(times, lambda) {
  -lambda * sum(times)
}

#' Analytical exponential score for exact observations
#' d/dlambda [n * log(lambda) - lambda * sum(t)] = n/lambda - sum(t)
exp_score_exact <- function(times, lambda) {
  n <- length(times)
  n / lambda - sum(times)
}

#' Analytical exponential Hessian for exact observations
#' d^2/dlambda^2 = -n/lambda^2
exp_hessian_exact <- function(times, lambda) {
  n <- length(times)
  matrix(-n / lambda^2, nrow = 1, ncol = 1)
}
