#' AMMI Biplots with \pkg{ggplot2}
#'
#' @description Generates a high-quality biplot (PC1 vs PC2) for classical or 
#'   robust AMMI models using the \pkg{ggplot2} framework.
#'
#' @param model_res an object of class \code{rAMMI} generated by \code{\link{rAMMIModel}}.
#' @param colGen color for genotype labels. Defaults to `"gray47"`.
#' @param colEnv color for environment labels and vectors. Defaults to `"darkred"`.
#' @param sizeGen text size for genotype labels. Defaults to 6.
#' @param sizeEnv text size for environment labels. Defaults to 6.
#' @param titles logical. If `TRUE` (default), a title indicating the model 
#'   type is added to the plot.
#' @param footnote logical. If `TRUE` (default), a caption with the percentage 
#'   of explained GxE variation is added at the bottom.
#' @param axis_expand numeric value to expand the axis limits. Useful to prevent 
#'   labels from being cut off. Defaults to 1.2.
#' @param limits logical. If `TRUE` (default), uses \code{coord_fixed()} to 
#'   maintain a 1:1 aspect ratio between axes.
#' @param axes logical. If `TRUE` (default), draws dashed horizontal and 
#'   vertical lines passing through the origin (0,0).
#' @param axislabels logical. If `TRUE` (default), includes axis titles with 
#'   the percentage of variance explained by each principal component.
#'
#' @details 
#' the biplot is constructed using a scaling factor of 0.5 (symmetric scaling), 
#' which allows representing both genotypes and environments in the same 
#' algebraic space. Genotypes are displayed as points (text), and environments 
#' are represented as vectors from the origin.
#'
#' @return A \pkg{ggplot2} object. This allows further customization using 
#'   standard ggplot layers (e.g., \code{+ theme_bw()}).
#'
#' @import ggplot2
#' @export
#' 
#' @examples
#' library(agridat)
#' data(yan.winterwheat)
#' 
#' # Classical AMMI
#' mod_ammi <- rAMMIModel(yan.winterwheat, genotype = "gen", 
#'                        environment = "env", response = "yield", type = "AMMI")
#' 
#' rAMMIPlot(mod_ammi,sizeGen=4,sizeEnv=4)
#' 
#' data(plrv)
#' mod_ammi_rep <- rAMMIModel(plrv, genotype="Genotype", environment="Locality", 
#'                         response="Yield", rep="Rep", type="AMMI")
#' rAMMIPlot(mod_ammi_rep,sizeGen=4,sizeEnv=4)
#'
rAMMIPlot <- function(model_res, colGen = "gray47", colEnv = "darkred", sizeGen = 6, sizeEnv = 6, 
                      titles = TRUE, footnote = TRUE, axis_expand = 1.2, limits = TRUE, 
                      axes = TRUE, axislabels = TRUE) {
  
  if (!inherits(model_res, "rAMMI")) stop("Se requiere un objeto de clase 'rAMMI'")
  type <- label <- d1 <- d2 <- x0 <- y0 <- radio <- NULL

  scaling <- 0.5
  idx <- 1:model_res$Ncomp
  lambda_scaling <- model_res$eigenvalues[idx]^scaling
  
  coordgenotype <- t(t(model_res$gen_scores[, idx]) / lambda_scaling)
  coordenviroment <- t(t(model_res$env_scores[, idx]) * lambda_scaling)
  
  varexpl <- round((model_res$eigenvalues[idx]^2 / model_res$vartotal) * 100, 2)
  
  plotdata <- data.frame(
    rbind(
      data.frame(coordgenotype, type = "genotype", label = model_res$gen_labels),
      data.frame(coordenviroment, type = "environment", label = model_res$env_labels)
    )
  )
  colnames(plotdata)[1:2] <- c("Component1", "Component2")
  
  p <- ggplot(data = plotdata, aes(x = Component1, y = Component2)) +
    theme_classic()
  
  if (axes) {
    p <- p + geom_vline(xintercept = 0, linetype = "dashed", alpha = 0.5) +
      geom_hline(yintercept = 0, linetype = "dashed", alpha = 0.5)
  }
  
  p <- p + 
    geom_segment(data = subset(plotdata, type == "environment"),
                 aes(x = 0, y = 0, xend = Component1, yend = Component2),
                 arrow = arrow(length = unit(0.2, "cm")), col = colEnv, alpha = 0.7) +
    geom_text(data = subset(plotdata, type == "environment"),
              aes(label = label), col = colEnv, size = sizeEnv, vjust = -0.5) +
    geom_text(data = subset(plotdata, type == "genotype"),
              aes(label = label), col = colGen, size = sizeGen)
  
  if (titles) p <- p + ggtitle(paste("AMMI Biplot - Model:", model_res$type))
  
  if (axislabels) {
    p <- p + xlab(paste0("PC1 (", varexpl[1], "%)")) +
      ylab(paste0("PC2 (", varexpl[2], "%)"))
  }
  
  if (footnote) {
    foot_txt <- paste(model_res$type, "biplot explaining", sum(varexpl), "% of GxE variation")
    p <- p + labs(caption = foot_txt)
  }
  
  if (limits) p <- p + coord_fixed(ratio = 1)
  
  return(p)
}