suppressPackageStartupMessages({
  library(MALDIquant)
  library(MALDIquantForeign)
  library(ggplot2)
  library(ggrepel)
  library(dplyr)
  library(stringr)
  library(readr)
})

## ===================== Configuration =====================
# File paths
base_path <- "/home/sierra/Documentos/Analisis de datos/Analisis de datos R"
file_std  <- file.path(base_path, "Fragmentos/Escopolamina_tuneo_fraq_20ev.mzML")
file_smp  <- file.path(base_path, "Fragmentos/LD_LTP_MS_cot_fraq_304.mzML")
output_dir <- file.path(base_path, "Fragmentos/Resultados_MS2/Comparativos")
output_file <- file.path(output_dir, "Mirror_Plot_Scopolamine_304_Academic.png")

# Plotting parameters
mz_range        <- c(80, 320)
label_threshold <- 0.05
topN_labels     <- 8
dpi_png         <- 300
bar_width_Da    <- 0.2

# Preprocessing parameters
halfWindowSize <- 5
snr_peaks      <- 2.0
tolerance_Da   <- 0.02

## ===================== Utilities =====================
massSpectrum_to_df <- function(sp) data.frame(mz = mz(sp), intensity = intensity(sp))

# Refined centroid (intensity-weighted)
refine_centroid <- function(df, m0, w) {
  sub <- df[df$mz >= (m0 - w) & df$mz <= (m0 + w), ]
  if (nrow(sub) == 0) return(m0)
  sum(sub$mz * sub$intensity) / sum(sub$intensity)
}

# Preprocessing pipeline for a single file (averaging scans if multiple exist)
process_file <- function(f) {
  scans <- importMzMl(f)
  if (length(scans) > 1) {
    scans <- smoothIntensity(scans, method = "SavitzkyGolay", halfWindowSize = 7)
    scans <- removeBaseline(scans, method = "SNIP", iterations = 60)
    scans <- calibrateIntensity(scans, method = "TIC")
    # Basic alignment if multiple scans
    pks <- detectPeaks(scans, method = "MAD", halfWindowSize = halfWindowSize, SNR = 1.5)
    ref <- referencePeaks(pks, minFrequency = 0.5, tolerance = tolerance_Da)
    scans <- alignSpectra(scans, halfWindowSize = halfWindowSize, SNR = 1.5, tolerance = tolerance_Da, reference = ref)
    spec_avg <- averageMassSpectra(scans, method = "mean")
  } else {
    spec_avg <- scans[[1]]
    spec_avg <- smoothIntensity(spec_avg, method = "SavitzkyGolay", halfWindowSize = 7)
    spec_avg <- removeBaseline(spec_avg, method = "SNIP", iterations = 60)
    spec_avg <- calibrateIntensity(spec_avg, method = "TIC")
  }
  return(spec_avg)
}

# Label generation
make_labels <- function(spec, df, rel_threshold = 0.05, topN = 5, w = tolerance_Da) {
  pk <- detectPeaks(spec, method = "MAD", halfWindowSize = halfWindowSize, SNR = snr_peaks)
  if (length(pk) == 0) return(NULL)
  
  lab_df <- data.frame(mz = mz(pk), intensity = intensity(pk))
  lab_df$mz <- vapply(lab_df$mz, function(m) refine_centroid(df, m, w), numeric(1))
  lab_df$rel_int <- lab_df$intensity / max(lab_df$intensity, na.rm = TRUE)
  
  # Select top N and those above threshold
  keep_idx <- unique(c(order(lab_df$rel_int, decreasing = TRUE)[seq_len(min(topN, nrow(lab_df)))],
                       which(lab_df$rel_int >= rel_threshold)))
  lab_df <- lab_df[sort(keep_idx), ]
  
  lab_df$label <- sprintf("%.2f", lab_df$mz)
  return(lab_df)
}

## ===================== Execution =====================
message("Processing Scopolamine spectra...")
spec_std <- process_file(file_std)
spec_smp <- process_file(file_smp)

df_std <- massSpectrum_to_df(spec_std) %>% mutate(intensity = intensity / max(intensity))
df_smp <- massSpectrum_to_df(spec_smp) %>% mutate(intensity = intensity / max(intensity))

labels_std <- make_labels(spec_std, df_std, label_threshold, topN_labels)
labels_smp <- make_labels(spec_smp, df_smp, label_threshold, topN_labels)

# Prepare mirrored data
df_smp$y <-  df_smp$intensity
df_std$y <- -df_std$intensity
df_smp$Group <- "Sample (Leaf)"
df_std$Group <- "Reference Standard"

# Combine for plotting
df_all <- bind_rows(df_smp, df_std)

# Filter by range
df_all <- df_all %>% filter(mz >= mz_range[1], mz <= mz_range[2])

message("Generating mirror plot...")
p <- ggplot() +
  # Mirror spectra (lines)
  geom_segment(data = df_smp %>% filter(mz >= mz_range[1], mz <= mz_range[2]), 
               aes(x = mz, xend = mz, y = 0, yend = y), color = "#1f77b4", linewidth = 0.3) +
  geom_segment(data = df_std %>% filter(mz >= mz_range[1], mz <= mz_range[2]), 
               aes(x = mz, xend = mz, y = 0, yend = y), color = "#d62728", linewidth = 0.3) +
  geom_hline(yintercept = 0, color = "black", linewidth = 0.5) +
  
  # Labels
  geom_text_repel(data = labels_smp, aes(x = mz, y = rel_int, label = label),
                  nudge_y = 0.05, size = 3.5, color = "#1f77b4", fontface = "bold",
                  max.overlaps = 20, min.segment.length = 0) +
  geom_text_repel(data = labels_std, aes(x = mz, y = -rel_int, label = label),
                  nudge_y = -0.05, size = 3.5, color = "#d62728", fontface = "bold",
                  max.overlaps = 20, min.segment.length = 0) +
  
  # English Academic Annotations
  scale_y_continuous(labels = function(x) abs(x) * 100, limits = c(-1.15, 1.15),
                     breaks = seq(-1, 1, 0.5)) +
  scale_x_continuous(limits = mz_range, breaks = seq(mz_range[1], mz_range[2], 20)) +
  labs(title = expression(bold("MS/MS Spectrum Comparison: Scopolamine (") * bolditalic("m/z") * bold(" 304.17)")),
       subtitle = "Upper: Scopolamine in Leaf (Sample) | Lower: Scopolamine Standard (Reference)\nCollision Energy: 20 eV",
       x = expression(italic(m/z)), 
       y = "Relative Abundance (%)") +
  theme_classic(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    plot.subtitle = element_text(hjust = 0.5, size = 11, lineheight = 1.2),
    axis.title = element_text(face = "bold"),
    axis.line = element_line(color = "black"),
    panel.grid.major.y = element_line(color = "grey90", linetype = "dotted")
  )

# Save plot
dir.create(output_dir, recursive = TRUE, showWarnings = FALSE)
ggsave(output_file, p, width = 11, height = 7, dpi = dpi_png)

message("✓ Mirror plot saved to: ", output_file)
