#!/usr/bin/env Rscript

# Build the compact, deployment-ready data object used by the Shiny app.
# The script reads only the verified study outputs bundled in source-data/.

suppressPackageStartupMessages({
  library(dplyr)
  library(readr)
  library(tidyr)
})

script_argument <- commandArgs(trailingOnly = FALSE)
script_flag <- grep("^--file=", script_argument, value = TRUE)
app_directory <- if (length(script_flag) == 1L) {
  dirname(normalizePath(sub("^--file=", "", script_flag)))
} else {
  normalizePath(getwd())
}

source_directory <- file.path(app_directory, "source-data")
data_directory <- file.path(app_directory, "data")
dir.create(data_directory, recursive = TRUE, showWarnings = FALSE)

read_source <- function(filename) {
  path <- file.path(source_directory, filename)
  if (!file.exists(path)) stop("Missing verified source file: ", path)
  read_csv(path, show_col_types = FALSE)
}

summarize_measure <- function(data, group_columns, measure_columns) {
  data |>
    pivot_longer(
      cols = all_of(measure_columns),
      names_to = "measure",
      values_to = "replication_value"
    ) |>
    group_by(across(all_of(c(group_columns, "measure")))) |>
    summarize(
      estimate = mean(replication_value, na.rm = TRUE),
      mc_sd = sd(replication_value, na.rm = TRUE),
      n_replications = sum(!is.na(replication_value)),
      mc_se = mc_sd / sqrt(n_replications),
      ci95_lo = estimate - 1.96 * mc_se,
      ci95_hi = estimate + 1.96 * mc_se,
      .groups = "drop"
    )
}

results <- readRDS(file.path(source_directory, "manuscript_simulation_results.rds"))

topology_raw <- read_source("topology_diagnostics_replication_level.csv") |>
  mutate(connected_percent = 100 * connected)

topology_diagnostics <- summarize_measure(
  topology_raw,
  c("density_condition", "network"),
  c(
    "n_edges", "density", "mean_degree", "degree_variance",
    "maximum_degree", "global_clustering", "mean_path_length",
    "connected_percent", "n_components", "n_isolates",
    "largest_component", "edges_added", "edges_removed"
  )
)

target_raw <- read_source("target_selection_replication_level.csv") |>
  transmute(
    density_condition,
    network,
    metric,
    most_tie_candidates = high_ties,
    average_tie_candidates = average_ties,
    least_tie_candidates = low_ties,
    percent_most_tied = 100 * (high_ties > 1),
    percent_average_tied = 100 * (average_ties > 1),
    percent_least_tied = 100 * (low_ties > 1),
    percent_most_average_same = 100 * high_average_same,
    percent_most_least_same = 100 * high_low_same,
    percent_average_least_same = 100 * average_low_same,
    centrality_score_sd = centrality_sd,
    eligible_vertices = eligible_n
  )

target_diagnostics <- summarize_measure(
  target_raw,
  c("density_condition", "network", "metric"),
  setdiff(names(target_raw), c("density_condition", "network", "metric"))
)

agreement_raw <- read_source("target_agreement_replication_level.csv") |>
  transmute(
    density_condition,
    network,
    metric_1,
    metric_2,
    percent_most_agreement = 100 * high_agreement,
    percent_average_agreement = 100 * average_agreement,
    percent_least_agreement = 100 * low_agreement
  )

target_agreement_diagnostics <- summarize_measure(
  agreement_raw,
  c("density_condition", "network", "metric_1", "metric_2"),
  c(
    "percent_most_agreement", "percent_average_agreement",
    "percent_least_agreement"
  )
)

weight_raw <- read_source("edge_weight_diagnostics_replication_level.csv") |>
  mutate(
    mean_edge_weight = weight_sum / n_weights,
    edge_weight_sd = sqrt(
      pmax(
        0,
        (weight_sum_squares - (weight_sum ^ 2) / n_weights) /
          pmax(1, n_weights - 1)
      )
    ),
    percent_graphs_rescaled = 100 * (scale_factor < (1 - 1e-12))
  )

edge_weight_diagnostics <- summarize_measure(
  weight_raw,
  c("density_condition", "network"),
  c(
    "mean_edge_weight", "edge_weight_sd", "minimum_weight",
    "maximum_weight", "within_graph_sd", "percent_graphs_rescaled",
    "scale_factor"
  )
)

app_data <- c(
  results,
  list(
    topology_diagnostics_mc = topology_diagnostics,
    target_diagnostics_mc = target_diagnostics,
    target_agreement_diagnostics_mc = target_agreement_diagnostics,
    edge_weight_diagnostics_mc = edge_weight_diagnostics
  )
)

saveRDS(app_data, file.path(data_directory, "cascade_results_explorer.rds"))

data_dictionary <- tribble(
  ~view, ~display_name, ~source_field, ~definition,
  "Final cascade extent", "Mean final failure rate", "mean_final_active", "Mean proportion of the 20 vertices active when the cascade stopped.",
  "Final cascade extent", "Monte Carlo SE", "se_final_active", "Between-replication SD divided by the square root of the number of replications.",
  "Final cascade extent", "95% Monte Carlo interval", "ci95_lo_final_active; ci95_hi_final_active", "Normal-approximation interval describing simulation precision around the condition mean.",
  "Most-least contrast", "Mean Delta_F", "mean_high_low_difference", "Mean paired final-failure-rate difference: most-central target minus least-central target.",
  "Most-least contrast", "Monte Carlo SE of Delta_F", "se_high_low_difference", "Monte Carlo SE of the mean paired contrast.",
  "Most-least contrast", "% with Delta_F > 0", "percent_high_greater", "Percentage of matched replications in which the most-central target produced the larger final cascade.",
  "Steps to total failure", "Complete cascades", "n_complete_failures", "Replications in which all 20 vertices became active.",
  "Steps to total failure", "Completion percentage", "percent_complete_failures", "Percentage of all replications reaching complete failure.",
  "Steps to total failure", "Conditional mean steps", "mean_steps_to_complete_failure", "Mean synchronous state-changing update layers among complete cascades only.",
  "Steps to total failure", "Conditional Monte Carlo SE", "se_steps_to_complete_failure", "Conditional SD divided by the square root of the number of complete cascades.",
  "Graph diagnostics", "Connected graphs", "connected_percent", "Percentage of realized graphs having one connected component.",
  "Target diagnostics", "Target-selection agreement", "percent_*_agreement", "Percentage of replications in which two metrics selected the same vertex; this is not a centrality-score correlation.",
  "Replication data", "Final active vertices", "final_active_count", "Number of active vertices at the stopping point.",
  "Replication data", "Stopping-point steps", "steps_to_stopping_point", "Number of state-changing synchronous updates; zero indicates no activation after the forced seed."
)

write_csv(data_dictionary, file.path(data_directory, "data_dictionary.csv"))

message(
  "Prepared app data: ",
  normalizePath(file.path(data_directory, "cascade_results_explorer.rds"))
)
