#' Geweke's MCMC Convergence Diagnostic
#'
#' Computes Geweke's convergence diagnostic for MCMC chains by comparing the sample means of
#' early and late parts of the Markov chain.
#'
#' @param chain A numeric matrix or data frame where columns correspond to parameters and rows to iterations,
#'   or a numeric vector for a single parameter.
#' @param frac1 Fraction of the chain to take from the beginning (default: 0.1).
#' @param frac2 Fraction of the chain to take from the end (default: 0.5).
#'
#' @return A data frame containing:
#'   \item{parameter}{Name of the parameter.}
#'   \item{mean_first}{Mean of the initial fraction of iterations.}
#'   \item{mean_last}{Mean of the final fraction of iterations.}
#'   \item{z_score}{Geweke z-statistic.}
#'   \item{p_value}{Two-sided p-value for equality of means.}
#'   \item{converged}{Logical indicating whether convergence is supported at alpha = 0.05 level.}
#'
#' @details
#' Geweke's convergence diagnostic tests for equality of the mean of early simulations
#' (default first 10\%) and the mean of later iterations (default last 50\%). Under the null hypothesis
#' of convergence, the test statistic follows a standard normal distribution.
#'
#' @references
#' Geweke, J. (1992). Evaluating the accuracy of sampling-based approaches to the calculation of posterior moments.
#' \emph{Bayesian Statistics}, 4, 169-193.
#'
#' Pan, Z., & Balakrishnan, N. (2010). Multiple-Steps Step-Stress Accelerated Degradation Modeling Based on Wiener and Gamma Processes.
#' \emph{Communications in Statistics - Simulation and Computation}, 39(7), 1384-1402. \doi{10.1080/03610918.2010.496060}
#'
#' @export
#' @examples
#' set.seed(123)
#' sample_chain <- matrix(rnorm(1000), ncol = 2, dimnames = list(NULL, c("param1", "param2")))
#' diag_res <- geweke_diag(sample_chain)
#' print(diag_res)
geweke_diag <- function(chain, frac1 = 0.1, frac2 = 0.5) {
  if (is.vector(chain)) {
    pnames <- deparse(substitute(chain))
    if (length(pnames) == 0 || nchar(pnames) == 0) pnames <- "param"
    chain <- matrix(chain, ncol = 1, dimnames = list(NULL, pnames))
  } else {
    chain <- as.matrix(chain)
  }
  
  if (is.null(colnames(chain))) {
    colnames(chain) <- paste0("param", seq_len(ncol(chain)))
  }
  
  n <- nrow(chain)
  n1 <- floor(frac1 * n)
  n2 <- floor(frac2 * n)
  
  if (n1 < 2 || n2 < 2 || (n - n2 + 1) <= n1) {
    stop("Chain length is too short for the specified fractions.")
  }
  
  start2 <- n - n2 + 1
  
  spec_var <- function(x) {
    len <- length(x)
    v <- stats::var(x) / len
    # AR(1) spectral density at zero frequency estimation for robust variance of mean
    if (len > 10) {
      sd_val <- stats::sd(x)
      if (!is.na(sd_val) && sd_val > 1e-12) {
        r1 <- stats::cor(x[-1], x[-len])
        if (!is.na(r1) && abs(r1) < 0.99) {
          v <- v * (1 + r1) / (1 - r1)
        }
      }
    }
    return(max(v, 1e-12))
  }
  
  results <- list()
  for (j in seq_len(ncol(chain))) {
    x <- chain[, j]
    x1 <- x[1:n1]
    x2 <- x[start2:n]
    
    m1 <- mean(x1)
    m2 <- mean(x2)
    
    v1 <- spec_var(x1)
    v2 <- spec_var(x2)
    
    z <- (m1 - m2) / sqrt(v1 + v2)
    p_val <- 2 * (1 - stats::pnorm(abs(z)))
    
    results[[j]] <- data.frame(
      parameter = colnames(chain)[j],
      mean_first = m1,
      mean_last = m2,
      z_score = z,
      p_value = p_val,
      converged = (p_val > 0.05),
      stringsAsFactors = FALSE
    )
  }
  
  res_df <- do.call(rbind, results)
  rownames(res_df) <- NULL
  return(res_df)
}
