# Final numerical and file-level verification --------------------------------

expected_tables <- file.path(TABLES, paste0("Table_", c(2, 3, 4, 5, 7, 8, 11), ".csv"))
figure_stems <- c("Figure_1", "Figure_2a", "Figure_2b", "Figure_3", "Figure_4a", "Figure_4b", "Figure_5")
expected_figures <- c(file.path(FIG_PNG, paste0(figure_stems, ".png")),
                      file.path(FIG_PDF, paste0(figure_stems, ".pdf")))
expected <- c(expected_tables, expected_figures)
economic_effects_file <- file.path(OUTPUTS, "economic_effects_calculation.csv")
expected <- c(expected, economic_effects_file)

file_checks <- data.frame(
  file = substring(expected, nchar(ROOT) + 2L),
  exists = file.exists(expected),
  nonempty = file.exists(expected) & file.info(expected)$size > 0
)
if (!all(file_checks$exists & file_checks$nonempty)) {
  stop("Missing or empty deliverable(s): ", paste(file_checks$file[!(file_checks$exists & file_checks$nonempty)], collapse = ", "))
}

# Compare manuscript-facing headline values after rounding to the precision
# printed in the paper.  This catches accidental changes in samples, formulas,
# clustering, priors, or seeds while tolerating harmless floating-point noise.
t2 <- read.csv(file.path(TABLES, "Table_2.csv"), check.names = FALSE)
t3 <- read.csv(file.path(TABLES, "Table_3.csv"), check.names = FALSE)
t4 <- read.csv(file.path(TABLES, "Table_4.csv"), check.names = FALSE)
t5 <- read.csv(file.path(TABLES, "Table_5.csv"), check.names = FALSE)
t7 <- read.csv(file.path(TABLES, "Table_7.csv"), check.names = FALSE)
t8 <- read.csv(file.path(TABLES, "Table_8.csv"), check.names = FALSE)
economic_effects <- read.csv(economic_effects_file, check.names = FALSE)

assert_close <- function(actual, expected, tolerance, label) {
  if (length(actual) != length(expected) || any(!is.finite(actual)) || any(abs(actual - expected) > tolerance)) {
    stop(label, " differs from the finalized manuscript. Actual: ", paste(signif(actual, 7), collapse = ", "))
  }
}
assert_close(t2$mean[1:4], c(-0.091, 0.089, 0.762, 1.407), .0006, "Table 2 means")
assert_close(t3$estimate_study, c(.146, -.168, -.108), .0006, "Table 3 coefficients")
if (!identical(Sys.getenv("REPLICATION_QUICK_BMA"), "1")) {
  assert_close(t4$posterior_mean, c(.135, -.126, -.092), .0025, "Table 4 posterior means")
}
assert_close(t5$interaction_coefficient[1:13],
  c(-.121, -.153, -.043, -.104, -.036, .001, -.059, -.030, -.031, -.051, .078, .075, -.011),
  .0015, "Table 5 interaction coefficients")
assert_close(as.numeric(t7[1, c("p25", "median", "p75")]), c(-.490, .139, .958), .0015, "Table 7 trust quantiles")
assert_close(as.numeric(t7[2, c("p25", "median", "p75")]), c(.171, 1.056, 1.625), .0015, "Table 7 rule-of-law quantiles")
assert_close(t8$cr2_satterthwaite_p_value, c(.359, .100, .319), .0006, "Table 8 CR2 p-values")
assert_close(t8$wild_bootstrap_p_value, c(.407, .063, .307), .0006, "Table 8 wild-bootstrap p-values")
effect_value <- function(name) economic_effects$value[match(name, economic_effects$quantity)]
assert_close(effect_value("trust_p75_minus_p25"), 1.447648, 1e-6, "Discussion trust change")
assert_close(effect_value("fitted_slope_change_at_rule_of_law_p25"), .184449, 1e-6, "Discussion low-law fitted change")
assert_close(effect_value("implied_slope_percentile"), .929944, 1e-6, "Discussion implied percentile")
assert_close(effect_value("share_between_observed_p25_and_implied_slope"), .680719, 1e-6, "Discussion interval share")
assert_close(effect_value("fitted_slope_change_at_rule_of_law_p75"), -.041971, 1e-6, "Discussion high-law fitted change")

write.csv(file_checks, file.path(OUTPUTS, "deliverable_validation.csv"), row.names = FALSE)

# Manifest records content hashes and simple dimensions for auditing transfers.
manifest <- data.frame(
  file = file_checks$file,
  bytes = file.info(expected)$size,
  md5 = unname(tools::md5sum(expected)),
  rows = vapply(expected, function(path) if (grepl("\\.csv$", path)) nrow(read.csv(path, check.names = FALSE)) else NA_integer_, integer(1)),
  generated_at_utc = format(Sys.time(), tz = "UTC", usetz = TRUE)
)
write.csv(manifest, file.path(OUTPUTS, "reproduction_manifest.csv"), row.names = FALSE)
writeLines(capture.output(sessionInfo()), file.path(OUTPUTS, "sessionInfo.txt"))
message("All replication checks passed.")
