#' Diagnostic Visualizations for Improved Adaptive Type-II Progressive Censoring
#'
#' Generates diagnostic graphics (histogram, dot plot, empirical vs fitted survival curves, MCMC trace and autocorrelation plots).
#'
#' @param x An object of class \code{"impadapt2_sample"}, \code{"impadapt2_mle"}, \code{"impadapt2_mpse"}, or \code{"impadapt2_bayes"}.
#' @param ... Additional graphical arguments.
#'
#' @return No return value, called for side effects (plotting).
#'
#' @export
#' @examples
#' set.seed(123)
#' ge_cdf <- function(x, par) (1 - exp(-par[2] * x))^par[1]
#' ge_pdf <- function(x, par) par[1] * par[2] * exp(-par[2] * x) * (1 - exp(-par[2] * x))^(par[1] - 1)
#' ge_qdf <- function(p, par) - (1 / par[2]) * log(1 - p^(1 / par[1]))
#'
#' samp <- r_impadapt2_censor(
#'   n = 20, m = 10, T1 = 0.8, T2 = 2.0,
#'   R = c(rep(1, 10)),
#'   pdf = ge_pdf, cdf = ge_cdf, qdf = ge_qdf,
#'   par = c(1.5, 0.8)
#' )
#' plot(samp)
plot_impadapt2_sample <- function(x, ...) {
  if (!inherits(x, "impadapt2_sample")) {
    stop("Object 'x' must be of class 'impadapt2_sample'.")
  }
  plot(x, ...)
}

#' @export
plot.impadapt2_sample <- function(x, ...) {
  oldpar <- graphics::par(no.readonly = TRUE)
  on.exit(graphics::par(oldpar))
  
  graphics::par(mfrow = c(1, 3), mar = c(4.5, 4.5, 3, 1))
  
  obs_data <- x$data
  
  graphics::hist(obs_data, probability = TRUE, main = paste("Histogram (", x$case, ")", sep = ""),
                 xlab = "Observed Failure Times", col = "#4C72B0", border = "white")
  if (length(obs_data) > 3) {
    graphics::lines(stats::density(obs_data), col = "#D55E00", lwd = 2)
  }
  graphics::abline(v = x$T1, col = "#009E73", lty = 2, lwd = 1.5)
  if (!is.infinite(x$T2)) graphics::abline(v = x$T2, col = "#CC79A7", lty = 2, lwd = 1.5)
  
  graphics::stripchart(obs_data, method = "jitter", pch = 19, col = "#0072B2",
                       main = "Failure Times Dot Plot", xlab = "Time")
  graphics::abline(v = x$T1, col = "#009E73", lty = 2, lwd = 1.5)
  if (!is.infinite(x$T2)) graphics::abline(v = x$T2, col = "#CC79A7", lty = 2, lwd = 1.5)
  
  if (length(obs_data) > 2) {
    stats::acf(obs_data, main = "Autocorrelation (ACF)", col = "#D55E00", lwd = 2)
  } else {
    graphics::plot.new()
    graphics::text(0.5, 0.5, "Insufficient sample size for ACF")
  }
  
  invisible(NULL)
}

#' @export
plot.impadapt2_mle <- function(x, ...) {
  oldpar <- graphics::par(no.readonly = TRUE)
  on.exit(graphics::par(oldpar))
  
  graphics::par(mfrow = c(1, 2), mar = c(4.5, 4.5, 3, 1))
  
  obs_data <- x$data
  grid_x <- seq(max(1e-4, min(obs_data) * 0.5), max(obs_data) * 1.3, length.out = 300)
  
  graphics::hist(obs_data, probability = TRUE, main = "MLE Fitted Density",
                 xlab = "Time", col = "#56B4E9", border = "white")
  dens_fit <- x$pdf(grid_x, x$par)
  graphics::lines(grid_x, dens_fit, col = "#D55E00", lwd = 2)
  
  fn_ecdf <- stats::ecdf(obs_data)
  emp_surv <- 1 - fn_ecdf(grid_x)
  fit_surv <- 1 - x$cdf(grid_x, x$par)
  
  graphics::plot(grid_x, emp_surv, type = "s", col = "#0072B2", lwd = 2,
                 main = "Empirical vs Fitted Survival", xlab = "Time", ylab = "S(t)")
  graphics::lines(grid_x, fit_surv, col = "#D55E00", lwd = 2, lty = 2)
  graphics::legend("topright", legend = c("Empirical", "MLE Fit"),
                   col = c("#0072B2", "#D55E00"), lty = c(1, 2), lwd = 2)
  
  invisible(NULL)
}

#' @export
plot.impadapt2_mpse <- function(x, ...) {
  oldpar <- graphics::par(no.readonly = TRUE)
  on.exit(graphics::par(oldpar))
  
  graphics::par(mfrow = c(1, 2), mar = c(4.5, 4.5, 3, 1))
  
  obs_data <- x$data
  grid_x <- seq(max(1e-4, min(obs_data) * 0.5), max(obs_data) * 1.3, length.out = 300)
  
  fn_ecdf <- stats::ecdf(obs_data)
  emp_cdf <- fn_ecdf(grid_x)
  fit_cdf <- x$cdf(grid_x, x$par)
  
  graphics::plot(grid_x, emp_cdf, type = "s", col = "#0072B2", lwd = 2,
                 main = "MPSE Fitted CDF", xlab = "Time", ylab = "F(t)")
  graphics::lines(grid_x, fit_cdf, col = "#E69F00", lwd = 2, lty = 2)
  graphics::legend("bottomright", legend = c("Empirical CDF", "MPSE Fit"),
                   col = c("#0072B2", "#E69F00"), lty = c(1, 2), lwd = 2)
  
  graphics::plot(grid_x, 1 - fit_cdf, type = "l", col = "#E69F00", lwd = 2,
                 main = "MPSE Survival Curve S(t)", xlab = "Time", ylab = "S(t)")
  
  invisible(NULL)
}

#' @export
plot.impadapt2_bayes <- function(x, ...) {
  oldpar <- graphics::par(no.readonly = TRUE)
  on.exit(graphics::par(oldpar))
  
  chain <- x$chain
  n_par <- ncol(chain)
  
  graphics::par(mfrow = c(n_par, 2), mar = c(4, 4.5, 2.5, 1))
  
  for (j in seq_len(n_par)) {
    par_name <- colnames(chain)[j]
    graphics::plot(chain[, j], type = "l", col = "#0072B2",
                   main = paste("Traceplot of", par_name),
                   xlab = "Iteration", ylab = par_name)
    graphics::abline(h = x$bayes_sel[j], col = "#D55E00", lwd = 2, lty = 2)
    
    graphics::plot(stats::density(chain[, j]), col = "#D55E00", lwd = 2,
                   main = paste("Posterior Density of", par_name),
                   xlab = par_name, ylab = "Density")
    graphics::abline(v = x$hpd_interval[j, ], col = "#009E73", lty = 3, lwd = 1.5)
  }
  
  invisible(NULL)
}
