knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
set.seed(20260815)
library(flexsynth)

n_pat <- 50
patients <- data.frame(
  id     = seq_len(n_pat),
  sex    = sample(c("F", "M"), n_pat, replace = TRUE, prob = c(0.45, 0.55)),
  age    = round(rnorm(n_pat, 64, 11)),
  smoker = sample(c(FALSE, TRUE), n_pat, replace = TRUE, prob = c(0.7, 0.3))
)

adm <- do.call(rbind, lapply(patients$id, function(pid) {
  k <- 1 + rpois(1, 0.6)
  data.frame(id = pid, admission_id = seq_len(k),
             los_days = 1 + rpois(k, 3))
}))

labs <- do.call(rbind, lapply(seq_len(nrow(adm)), function(i) {
  k <- 1 + rpois(1, 2)
  data.frame(id = adm$id[i], admission_id = adm$admission_id[i],
             lab_number = seq_len(k),
             analyte = sample(c("troponin", "LDL", "creatinine"), k, replace = TRUE),
             value   = round(abs(rnorm(k, 2, 1.5)), 2))
}))

tables <- list(patients = patients, admissions = adm, labs = labs)
vapply(tables, nrow, integer(1))

structures <- list(
  patients   = ~ id,
  admissions = ~ id / admission_id,
  labs       = ~ id / admission_id / lab_number
)
keys <- list(
  patients   = "id",
  admissions = c("id", "admission_id"),
  labs       = c("id", "admission_id", "lab_number")
)

res <- synth_linked(tables, structures = structures, keys = keys, seed = 1)
res

syn <- as.list(res)
check_linkage(res)

# every synthetic lab points at a real (synthetic) admission — no orphans
all(paste(syn$labs$id, syn$labs$admission_id) %in%
    paste(syn$admissions$id, syn$admissions$admission_id))

diagnose(tables, res)

disclosure_risk(patients, syn$patients,
                quasi = c("age", "sex", "smoker"), seed = 1)

