#' @title Align GSEA Performance Data with System Monitoring Data

#' @description Aligns timestamps generated by batch_calc_gsea with CSV data from

#'   an independent monitoring script, producing a time series data frame suitable

#'   for publication.

#' @param gsea_res A GseaRes object (must contain metadata$gsea_benchmark)

#' @param monitor_csv Path to the CSV file generated by the monitoring script

#' @return A aligned data frame (containing unified time axis fields such as relative_sec)

#' @noRd

#' @examples

#' \dontrun{

#' res <- readRDS("GSEA_Capsule_[...].rds")

#' aligned <- align_benchmark_data(res, "system_monitor.csv")

#' plot(aligned$relative_sec, aligned$rss_mb, type = "l")

#' }

align_benchmark_data <- function(gsea_res, monitor_csv) {

    if (!inherits(gsea_res, "GseaRes")) {

    stop("Input must be a GseaRes object")

    }



    if (!file.exists(monitor_csv)) {

    stop("Monitoring CSV does not exist: ", monitor_csv)

    }



    # 提取GSEA时间窗口

    bench <- gsea_res$metadata$gsea_benchmark

    start_ms <- bench$start_ms

    end_ms <- bench$end_ms



    # 读取Python生成的CSV（格式更简洁）

    monitor <- read.csv(monitor_csv, stringsAsFactors = FALSE)



    # Python和R的时间戳都是Unix毫秒，直接对齐

    aligned <- monitor[monitor$timestamp_ms >= (start_ms - 5000) &

    monitor$timestamp_ms <= (end_ms + 5000), ]



    if (nrow(aligned) == 0) {

    warning("No overlapping time data found")

    return(NULL)

    }



    # 转换相对时间（秒）

    aligned$relative_sec <- (aligned$timestamp_ms - start_ms) / 1000



    # 阶段标记

    total_duration <- (end_ms - start_ms) / 1000

    aligned$phase <- ifelse(

    aligned$relative_sec < 0, "pre_start",

    ifelse(aligned$relative_sec > total_duration, "post_end",

            ifelse(aligned$relative_sec < total_duration * 0.2, "startup",

        ifelse(aligned$relative_sec < total_duration * 0.8, "core_compute", "cleanup")

            )

    )

    )



    attr(aligned, "gsea_info") <- bench

    class(aligned) <- c("GseaBenchmarkAligned", "data.frame")



    message(sprintf(

    "Alignment complete: %d sampling points, spanning %.1f seconds",

    nrow(aligned), max(aligned$relative_sec) - min(aligned$relative_sec)

    ))



    invisible(aligned)

}





# Section: Visualization ----



#' @importFrom ggplot2 ggplot aes geom_line geom_vline labs theme_minimal scale_color_manual

#' @title Plot GSEA Benchmark Memory Curve

#' @description Generates a standard memory usage curve plot for publication.

#' @param aligned_data Aligned data frame returned by align_benchmark_data

#' @param highlight_phases Whether to color by phase, default TRUE

#' @return A ggplot object

#' @export

#' @examples

#' # Build a small synthetic aligned-data frame (mimics the output of

#' # align_benchmark_data() without needing an external CSV or GseaRes object).

#' syn <- data.frame(

#'   timestamp_ms = seq(0, 20000, by = 1000),

#'   rss_mb = c(120, 150, 220, 280, 310, 330, 340, 335, 320, 305,

#'              290, 270, 255, 245, 240, 235, 230, 225, 220, 215, 210),

#'   relative_sec = seq(0, 20, by = 1),

#'   phase = c(rep("startup", 4), rep("core_compute", 12), rep("cleanup", 5))

#' )

#' attr(syn, "gsea_info") <- list(duration_sec = 20, workers = 2)

#' class(syn) <- c("GseaBenchmarkAligned", "data.frame")

#' plot_gsea_memory(syn)

#' plot_gsea_memory(syn, highlight_phases = FALSE)

plot_gsea_memory <- function(aligned_data, highlight_phases = TRUE) {

    if (!requireNamespace("ggplot2", quietly = TRUE)) {

    stop("ggplot2 package required: install.packages('ggplot2')")

    }



    info <- attr(aligned_data, "gsea_info")



    p <- ggplot2::ggplot(aligned_data, ggplot2::aes(x = relative_sec, y = rss_mb)) +

    ggplot2::geom_line(linewidth = 0.8, color = "steelblue") +

    ggplot2::geom_vline(xintercept = 0, linetype = "dashed", color = "darkgreen") +

    ggplot2::geom_vline(xintercept = info$duration_sec, linetype = "dashed", color = "darkred") +

    ggplot2::labs(

            title = sprintf("GSEA Memory Usage Profile (%d cores)", info$workers),

            subtitle = sprintf("Total duration: %.1f seconds", info$duration_sec),

            x = "Time (seconds from GSEA start)",

            y = "Memory (MB)",

            caption = sprintf(

        "Peak: %.0f MB | Average: %.0f MB",

        max(aligned_data$rss_mb, na.rm = TRUE),

        mean(aligned_data$rss_mb[aligned_data$phase %in% c("startup", "core_compute", "cleanup")], na.rm = TRUE)

            )

    ) +

    ggplot2::theme_minimal()



    if (highlight_phases) {

    # 添加阶段背景色（高级用法，可选）

    p <- p + ggplot2::aes(color = phase) +

            ggplot2::scale_color_manual(values = c(

        pre_start = "gray70",

        startup = "green3",

        core_compute = "steelblue",

        cleanup = "orange",

        post_end = "gray70"

            ), name = "Phase")

    }



    p

}





# Section: Print Method ----



#' @title Print Method for GSEA Benchmark Alignment Results

#' @description Formats and displays a summary of aligned GSEA benchmark data,

#'   including computation parameters, monitoring statistics, and phase-wise

#'   memory usage.

#' @param x An object of class 'GseaBenchmarkAligned'

#' @param ... Additional arguments passed to print

#' @return The input object x (invisibly)

#' @noRd

#' @exportS3Method

#' @examples

#' \dontrun{

#' data <- align_benchmark_data(gsea_res, "system_monitor.csv")

#' print(data)

#' }

print.GseaBenchmarkAligned <- function(x, ...) {

    info <- attr(x, "gsea_info")



    # NOTE: cat() is the idiomatic way to write to stdout inside an S3 print()

    # method (cf. print.data.frame, print.lm). Do NOT convert to message(),

    # which would redirect output to stderr and break interactive use.

    cat("========================================\n")

    cat("   GSEA Benchmark Alignment Results\n")

    cat("========================================\n")

    cat(sprintf("GSEA Computation Time: %s\n", info$start_time))

    cat(sprintf("Parallel Cores:        %d\n", info$workers))

    cat(sprintf("GSEA Total Duration:   %.2f seconds\n", info$duration_sec))

    cat("----------------------------------------\n")

    cat(sprintf("Monitoring Samples:    %d\n", nrow(x)))

    cat(sprintf(

    "Monitoring Span:       %.1f seconds (%.1f to %.1f)\n",

    max(x$relative_sec) - min(x$relative_sec),

    min(x$relative_sec), max(x$relative_sec)

    ))

    cat(sprintf("Peak Memory:           %.0f MB\n", max(x$rss_mb, na.rm = TRUE)))

    cat(sprintf("Average Memory:        %.0f MB\n", mean(x$rss_mb[x$phase %in% c("startup", "core_compute", "cleanup")], na.rm = TRUE)))

    cat("========================================\n")



    # 各阶段统计

    cat("\nMemory Statistics by Phase:\n")

    stage_stats <- tapply(x$rss_mb, x$phase, function(v) {

    sprintf("Mean %.0f MB, Peak %.0f MB", mean(v, na.rm = TRUE), max(v, na.rm = TRUE))

    })

    for (phase in names(stage_stats)) {

    if (!is.na(stage_stats[phase])) {

            cat(sprintf("  [%s]: %s\n", phase, stage_stats[phase]))

    }

    }



    invisible(x)

}





# Section: Scalability Analysis ----



#' @title Generate Scalability Analysis Report (Multi-core Comparison)

#' @description Compares GSEA performance across different core counts (for publication).

#' @param gsea_res_list A list of multiple GseaRes objects (named e.g., list("1_core" = res1, "4_core" = res4))

#' @param monitor_csv_list Corresponding list of monitoring CSV paths (with same names as gsea_res_list)

#' @return A comparison data frame with columns: run_name, workers, duration_sec, mem_peak_mb (if available), mem_avg_mb (if available)

#' @noRd

#' @examples

#' \dontrun{

#' results <- analyze_scalability(

#'   gsea_res_list = list("1_core" = res1, "4_core" = res4),

#'   monitor_csv_list = c("1_core" = "monitor_1.csv", "4_core" = "monitor_4.csv")

#' )

#' print(results)

#' }

analyze_scalability <- function(gsea_res_list, monitor_csv_list = NULL) {

    if (is.null(names(gsea_res_list))) {

    names(gsea_res_list) <- paste0("run_", seq_along(gsea_res_list))

    }



    results <- lapply(names(gsea_res_list), function(name) {

    res <- gsea_res_list[[name]]



    if (is.null(res$metadata$gsea_benchmark)) {

            warning(name, " missing benchmark data, skipping")

            return(NULL)

    }



    bench <- res$metadata$gsea_benchmark



    # 基础信息

    out <- data.frame(

            run_name = name,

            workers = bench$workers,

            duration_sec = bench$duration_sec,

            stringsAsFactors = FALSE

    )



    # 如果有监控数据，添加内存统计

    if (!is.null(monitor_csv_list) && name %in% names(monitor_csv_list)) {

            csv_path <- monitor_csv_list[[name]]

            if (file.exists(csv_path)) {

        monitor <- read.csv(csv_path, stringsAsFactors = FALSE)

        # 筛选GSEA时间段

        aligned <- monitor[monitor$timestamp_ms >= bench$start_ms &

                    monitor$timestamp_ms <= bench$end_ms, ]

        if (nrow(aligned) > 0) {

                    out$mem_peak_mb <- max(aligned$rss_mb, na.rm = TRUE)

                    out$mem_avg_mb <- mean(aligned$rss_mb, na.rm = TRUE)

        }

            }

    }



    out

    })



    do.call(rbind, results)

}

