# Copyright (c) 2026 INNOVATIO SAS
# SPDX-License-Identifier: MIT
# Reference environment: R 4.5.1, survival 3.8-3

args <- commandArgs(trailingOnly = TRUE)
csv_path <- if (length(args)) args[[1]] else "msc-p030-retention-survival.csv"
d <- read.csv(csv_path, stringsAsFactors = FALSE)
required <- c("duration_months", "churn_event", "plan_group", "baseline_engagement_z")
missing_columns <- setdiff(required, names(d))
if (length(missing_columns)) stop(paste("missing required columns:", paste(missing_columns, collapse = ", ")))
invalid <- !complete.cases(d[required]) |
  !is.finite(d$duration_months) | d$duration_months <= 0 |
  !(d$churn_event %in% c(0, 1)) |
  !(d$plan_group %in% c("monthly", "annual")) |
  !is.finite(d$baseline_engagement_z)
if (any(invalid)) stop(sprintf("%d invalid or incomplete rows; analysis aborted without imputation", sum(invalid)))
stopifnot(nrow(d) > 0)
d$annual <- as.integer(d$plan_group == "annual")

suppressPackageStartupMessages(library(survival))
survival_object <- Surv(d$duration_months, d$churn_event)
km <- survfit(survival_object ~ plan_group, data = d, conf.type = "log-log")
print(summary(km, times = c(9, 12, 18), extend = TRUE))
print(survdiff(survival_object ~ plan_group, data = d, rho = 0))

fit <- coxph(survival_object ~ annual + baseline_engagement_z, data = d, ties = "breslow", x = TRUE)
print(summary(fit))

fit_ph <- coxph(
  survival_object ~ annual + baseline_engagement_z + tt(annual),
  data = d,
  ties = "breslow",
  tt = function(x, t, ...) x * log(t / 12)
)
print(summary(fit_ph))
cat("scope: synthetic observational association; no causal or individual-probability claim\n")
