preprocess_events <- function(df, horizon_cols, code_cols) {
    stopifnot(length(horizon_cols) >= 1)
    stopifnot(length(code_cols) >= 1)
    
    out <- df
    
    if (!"Start" %in% names(out)) {
        out$Start <- seq_len(nrow(out))
    } else {
        out$Start <- suppressWarnings(as.numeric(out$Start))
        if (all(is.na(out$Start))) {
            out$Start <- seq_len(nrow(out))
        } else {
            na_idx <- is.na(out$Start)
            if (any(na_idx)) {
                out$Start[na_idx] <- seq_len(sum(na_idx)) + max(out$Start, na.rm = TRUE)
            }
        }
    }
    
    if (!"EventIndex" %in% names(out)) {
        out$EventIndex <- seq_len(nrow(out))
    } else {
        out$EventIndex <- suppressWarnings(as.numeric(out$EventIndex))
        if (all(is.na(out$EventIndex))) {
            out$EventIndex <- seq_len(nrow(out))
        } else {
            na_idx <- is.na(out$EventIndex)
            if (any(na_idx)) {
                out$EventIndex[na_idx] <- seq_len(sum(na_idx)) + max(out$EventIndex, na.rm = TRUE)
            }
        }
    }
    
    if (!"unique_index" %in% names(out)) {
        out$unique_index <- seq_len(nrow(out))
    } else {
        out$unique_index <- suppressWarnings(as.numeric(out$unique_index))
        if (all(is.na(out$unique_index))) {
            out$unique_index <- seq_len(nrow(out))
        } else {
            na_idx <- is.na(out$unique_index)
            if (any(na_idx)) {
                out$unique_index[na_idx] <- seq_len(sum(na_idx)) + max(out$unique_index, na.rm = TRUE)
            }
        }
    }
    
    out %>%
        mutate(
            across(all_of(code_cols), ~ as.integer(replace_na(suppressWarnings(as.numeric(.)), 0))),
            Start = as.numeric(Start),
            EventIndex = as.numeric(EventIndex),
            unique_index = as.numeric(unique_index)
        ) %>%
        arrange(across(all_of(horizon_cols)), Start, EventIndex, unique_index) %>%
        group_by(across(all_of(horizon_cols))) %>%
        mutate(
            horizon_id = dplyr::cur_group_id(),
            row_in_horizon = dplyr::row_number()
        ) %>%
        ungroup() %>%
        mutate(
            row_id = dplyr::row_number(),
            active_code_count = rowSums(across(all_of(code_cols))),
            eligible_for_sampling = active_code_count > 0
        )
}