#' Simulate a stochastic SEIR epidemic with latent OU transmission
#'
#' Generates a synthetic epidemic trajectory from the stochastic SEIR model
#' with exact Ornstein-Uhlenbeck log-transmission dynamics, as described in
#' Section 2 of Feng and Wang (2025).
#'
#' @param n_steps  Integer. Number of days to simulate.
#' @param kappa    Positive numeric. OU mean-reversion speed.
#' @param sigma_psi Positive numeric. OU continuous-time volatility.
#' @param mu_psi   Numeric. OU long-run mean of log-transmission.
#' @param x0       Numeric vector of length 5: initial state
#'                 \eqn{(S_0, E_0, I_0, R_0, \Psi_0)}.
#' @param fixed    Named list of fixed model parameters. Must contain:
#'   \describe{
#'     \item{eps}{Incubation rate \eqn{\epsilon} (1/mean incubation period).}
#'     \item{gamma}{Recovery rate \eqn{\gamma} (1/mean infectious period).}
#'     \item{delta}{Background mortality rate \eqn{\delta}.}
#'     \item{b}{Birth rate \eqn{b} (usually equal to \eqn{\delta}).}
#'     \item{q}{Case detection probability \eqn{q \in (0,1]}.}
#'     \item{N}{Reference population size \eqn{N}.}
#'     \item{sigma_comp}{Compartment diffusion coefficient \eqn{\sigma_\cdot}.}
#'   }
#'
#' @return A data frame with \eqn{T+1} rows (day 0 to day \eqn{T}) and columns:
#'   \code{day}, \code{S}, \code{E}, \code{I}, \code{R}, \code{Psi},
#'   \code{beta} (\eqn{e^{\Psi_t}}), \code{obs} (observed daily counts).
#'
#' @references
#' Feng, W. and Wang, W. (2025). Bayesian sequential inference for a stochastic SEIR model
#' with latent transmission dynamics. \emph{Preprint}.
#'
#' @export
#' @examples
#' fixed <- list(eps = 1/5, gamma = 1/10, delta = 1/(70*365),
#'               b = 1/(70*365), q = 0.3, N = 1e6, sigma_comp = 0.01)
#' x0 <- c(S = 1e6 - 100, E = 50, I = 50, R = 0, Psi = log(0.25))
#' traj <- seir_simulate(n_steps = 200, kappa = 0.05, sigma_psi = 0.10,
#'                       mu_psi = log(0.25), x0 = x0, fixed = fixed)
#' plot(traj$day, traj$obs, type = "l", xlab = "Day",
#'      ylab = "Daily cases", main = "Simulated epidemic")
seir_simulate <- function(n_steps, kappa, sigma_psi, mu_psi, x0, fixed) {
  stopifnot(n_steps > 0, kappa > 0, sigma_psi > 0, length(x0) == 5)
  ou   <- ou_params(kappa, sigma_psi)
  alpha <- ou$alpha; tau <- ou$tau

  eps  <- fixed$eps;   gam  <- fixed$gamma
  delt <- fixed$delta; b    <- fixed$b
  q    <- fixed$q;     N    <- fixed$N;  sc <- fixed$sigma_comp

  S   <- numeric(n_steps + 1); E   <- numeric(n_steps + 1)
  I   <- numeric(n_steps + 1); R   <- numeric(n_steps + 1)
  Psi <- numeric(n_steps + 1); obs <- numeric(n_steps + 1)

  S[1] <- x0[1]; E[1] <- x0[2]; I[1] <- x0[3]
  R[1] <- x0[4]; Psi[1] <- x0[5]
  obs[1] <- rpois(1, max(q * eps * E[1], 1e-10))

  for (t in seq_len(n_steps)) {
    s <- S[t]; e <- E[t]; i <- I[t]; r <- R[t]; psi <- Psi[t]
    beta <- exp(psi)
    foi  <- beta * s * i / N

    S[t+1]   <- max(s + (b * N - foi - delt * s)     + sc * rnorm(1), 0)
    E[t+1]   <- max(e + (foi  - (eps + delt) * e)    + sc * rnorm(1), 0)
    I[t+1]   <- max(i + (eps * e - (gam + delt) * i) + sc * rnorm(1), 0)
    R[t+1]   <- max(r + (gam * i - delt * r)          + sc * rnorm(1), 0)
    Psi[t+1] <- mu_psi + alpha * (psi - mu_psi) + tau * rnorm(1)
    obs[t+1] <- rpois(1, max(q * eps * E[t+1], 1e-10))
  }

  data.frame(
    day  = 0:n_steps,
    S    = S, E = E, I = I, R = R,
    Psi  = Psi,
    beta = exp(Psi),
    obs  = obs
  )
}
