# =============================================================================
# Diaspora congolaise : audiences de Meta et stocks de migrants des Nations unies
# Scripts R utilisés pour l'article « Où vit la diaspora congolaise ? Ce que disent Facebook et les Nations unies »
# Guerschom Mugisho, octobre 2026
#
# Partie 1 : collecte des audiences de Meta (produit meta_diaspora_rdc.csv)
# Partie 2 : analyse et comparaison avec les Nations unies (produit les tableaux des figures)
# Pour n'exécuter que l'analyse, mettre COLLECTER <- FALSE ci-dessous.
# =============================================================================

COLLECTER <- FALSE   # TRUE pour relancer la collecte (jeton Meta requis)

if (COLLECTER) {
  # =============================================================================
  # Diaspora congolaise : audiences publicitaires Meta (Facebook + Instagram)
  # Catégorie « A vécu en RDC (anciennement Expats - RDC) », identifiant 6023516373983 :
  # « personnes qui vivaient en RDC et qui vivent maintenant à l'étranger ».
  #
  # Pour chaque pays de résidence, chaque sexe et chaque groupe d'âge (18 ans et plus, âge minimal
  # de Meta pour ce type de catégorie) : nombre d'utilisateurs actifs mensuels ayant vécu en RDC.
  # 25 pays x 2 sexes x 6 groupes d'âge = 300 requêtes (environ 1 h 10).
  # Sortie : meta_diaspora_rdc.csv (fichier distinct des collectes précédentes).
  #
  # Utilisation (RStudio) :
  #   1. Coller le jeton ci-dessous (le même que pour les Philippines).
  #   2. Session > Set Working Directory > Choose Directory… (même dossier que d'habitude).
  #   3. Cliquer sur « Source ». Stop pour interrompre ; relancer reprend où l'on s'était arrêté.
  #   Ne jamais supprimer meta_diaspora_rdc.csv : c'est lui qui permet la reprise.
  # =============================================================================
  
  JETON    <- Sys.getenv("META_TOKEN", "COLLEZ_ICI_VOTRE_JETON")   # ne pas partager ce fichier une fois rempli
  COMPTE   <- "act_267606776766109"
  VERSION  <- "v26.0"
  SORTIE   <- "meta_diaspora_rdc.csv"
  PAUSE    <- 10
  EXPAT_RDC <- "6023516373983"
  
  # Pays de résidence : principales destinations de la migration congolaise (Europe, Amérique du Nord,
  # Afrique australe, centrale et de l'Est)
  PAYS <- c(FR = "France", BE = "Belgique", GB = "Royaume-Uni", DE = "Allemagne", NL = "Pays-Bas",
            CH = "Suisse", IT = "Italie", ES = "Espagne", SE = "Suède", IE = "Irlande", PT = "Portugal",
            US = "États-Unis", CA = "Canada",
            ZA = "Afrique du Sud", AO = "Angola", CG = "Congo-Brazzaville", UG = "Ouganda", RW = "Rwanda",
            BI = "Burundi", TZ = "Tanzanie", ZM = "Zambie", KE = "Kenya", CF = "Centrafrique",
            SS = "Soudan du Sud", AE = "Émirats arabes unis")
  # Groupes d'âge (65 = « 65 ans et plus » pour Meta)
  AGES <- list("18-65+" = c(18, 65), "18-29" = c(18, 29), "30-39" = c(30, 39), "40-49" = c(40, 49),
               "50-64" = c(50, 64), "65+" = c(65, 65))
  SEXES <- c("1" = "Hommes", "2" = "Femmes")
  
  for (p in c("httr2", "jsonlite")) if (!requireNamespace(p, quietly = TRUE)) install.packages(p)
  library(httr2); library(jsonlite)
  if (grepl("COLLEZ_ICI", JETON)) stop("Renseignez JETON en haut du script.")
  BASE <- paste0("https://graph.facebook.com/", VERSION)
  `%||%` <- function(a, b) if (is.null(a)) b else a
  
  ATTENTES <- c(60, 120, 300, 600, rep(900, 8))
  appel <- function(chemin, params) {
    for (i in seq_along(ATTENTES)) {
      req <- request(paste0(BASE, "/", chemin)) |>
        req_url_query(!!!c(params, access_token = JETON)) |>
        req_error(is_error = function(resp) FALSE) |>
        req_timeout(60)
      resp <- req_perform(req)
      js <- tryCatch(resp_body_json(resp, simplifyVector = FALSE), error = function(e) list())
      if (resp_status(resp) == 200) return(js)
      code <- js$error$code
      if (!is.null(code) && code %in% c(4, 17, 32, 613, 80004) || resp_status(resp) >= 500) {
        message("  limite atteinte (code ", code, "), pause ", ATTENTES[i], " s")
        Sys.sleep(ATTENTES[i]); next
      }
      stop("Erreur API ", resp_status(resp), " : ", toJSON(js$error, auto_unbox = TRUE))
    }
    stop("Trop d'échecs successifs : relancez plus tard, la collecte reprendra où elle s'est arrêtée.")
  }
  
  estimation <- function(pays, sexe, a_min, a_max) {
    spec <- list(geo_locations = list(countries = list(pays), location_types = list("home")),
                 age_min = a_min, age_max = a_max, genders = list(as.integer(sexe)),
                 publisher_platforms = list("facebook", "instagram"),
                 flexible_spec = list(list(behaviors = list(list(id = EXPAT_RDC)))))
    js <- appel(paste0(COMPTE, "/delivery_estimate"),
                list(optimization_goal = "REACH", targeting_spec = as.character(toJSON(spec, auto_unbox = TRUE))))
    d <- js$data[[1]]
    c(d$estimate_mau_lower_bound %||% NA, d$estimate_mau_upper_bound %||% NA)
  }
  
  deja <- if (file.exists(SORTIE)) with(read.csv(SORTIE, colClasses = "character"), paste(pays, sexe, ages)) else character()
  message(length(PAYS) * length(SEXES) * length(AGES), " requêtes prévues (", length(deja), " déjà dans ", SORTIE, ")")
  
  for (cp in names(PAYS)) for (s in names(SEXES)) for (ga in names(AGES)) {
    if (paste(cp, s, ga) %in% deja) next
    a <- AGES[[ga]]
    e <- estimation(cp, s, a[1], a[2])
    ligne <- data.frame(date = format(Sys.Date()), pays = cp, pays_nom = PAYS[[cp]], sexe = s, ages = ga,
                        mau_bas = e[1], mau_haut = e[2])
    write.table(ligne, SORTIE, sep = ",", row.names = FALSE, append = file.exists(SORTIE),
                col.names = !file.exists(SORTIE), fileEncoding = "UTF-8")
    message(PAYS[[cp]], " ", SEXES[[s]], " ", ga, " : ", e[1], "-", e[2])
    Sys.sleep(PAUSE)
  }
  message("Terminé -> ", normalizePath(SORTIE))
}

# =============================================================================
# PARTIE 2 : ANALYSE

# =============================================================================
# Diaspora congolaise : audiences de Meta (22 octobre 2026) et stocks de migrants des Nations unies (2024)
# Reproduit en R les calculs de analyse.py.
#
# Entrées (dossier de travail) :
#   meta_diaspora_rdc.csv                                   (collecte_diaspora_rdc.R)
#   undesa_pd_2024_ims_stock_by_sex_destination_and_origin.xlsx   (UN DESA, International Migrant Stock 2024)
# Sorties : diaspora_pays.csv, diaspora_ages.csv, diaspora_ages_regions.csv, diaspora_tendances.csv et un résumé dans la console.
# Paquets : readxl
# =============================================================================
if (!requireNamespace("readxl", quietly = TRUE)) install.packages("readxl")
library(readxl)

PLANCHER <- 1000
ONU_FICHIER <- "undesa_pd_2024_ims_stock_by_sex_destination_and_origin.xlsx"
M49 <- c(FR = 250, BE = 56, GB = 826, DE = 276, NL = 528, CH = 756, IT = 380, ES = 724, SE = 752, IE = 372, PT = 620,
         US = 840, CA = 124, ZA = 710, AO = 24, CG = 178, UG = 800, RW = 646, BI = 108, TZ = 834, ZM = 894, KE = 404,
         CF = 140, SS = 728, AE = 784)
AGES <- c("18-29", "30-39", "40-49", "50-64", "65+")
ANNEES <- c(1990, 1995, 2000, 2005, 2010, 2015, 2020, 2024)

# --- Meta : valeur centrale, plancher (1000-1000) compté 500 ---------------------------------
m <- read.csv("meta_diaspora_rdc.csv", stringsAsFactors = FALSE)
m$cens <- m$mau_haut <= PLANCHER
m$c <- ifelse(m$cens, PLANCHER / 2, (m$mau_bas + m$mau_haut) / 2)
val <- function(p, s, a) m$c[m$pays == p & m$sexe == s & m$ages == a]
cens <- function(p, s, a) m$cens[m$pays == p & m$sexe == s & m$ages == a]
pays <- unique(m$pays)

# --- Nations unies : tableau 1, origine RDC (code 180) ------------------------------------------
t1 <- as.data.frame(read_excel(ONU_FICHIER, sheet = "Table 1", skip = 11, col_names = FALSE))
rdc <- t1[t1[[7]] == 180, ]
onu <- function(code, col) { r <- rdc[rdc[[5]] == code, ]; if (nrow(r)) as.numeric(r[1, col]) else NA }
# colonnes : 8-15 total 1990-2024, 16-23 hommes, 24-31 femmes
tab <- do.call(rbind, lapply(pays, function(p) {
  data.frame(pays = p, nom = m$pays_nom[m$pays == p][1],
             meta_h = val(p, 1, "18-65+"), meta_f = val(p, 2, "18-65+"),
             meta_t = val(p, 1, "18-65+") + val(p, 2, "18-65+"),
             onu_t = onu(M49[[p]], 15), onu_h = onu(M49[[p]], 23), onu_f = onu(M49[[p]], 31),
             cens_sexe = cens(p, 1, "18-65+") | cens(p, 2, "18-65+"))
}))
tab$rapport <- tab$meta_t / tab$onu_t
tab$pct_f_meta <- ifelse(tab$cens_sexe, NA, 100 * tab$meta_f / tab$meta_t)
tab$pct_f_onu <- 100 * tab$onu_f / tab$onu_t
tab$max <- pmax(tab$meta_t, tab$onu_t, na.rm = TRUE)
tab <- tab[order(-tab$max), ]
write.csv(tab, "diaspora_pays.csv", row.names = FALSE)

# --- Structure par âge et par sexe selon Meta (figure 5) -----------------------------------------
ages <- do.call(rbind, lapply(pays, function(p) do.call(rbind, lapply(1:2, function(s)
  data.frame(pays = p, sexe = s, ages = AGES, effectif = sapply(AGES, function(a) val(p, s, a)),
             plancher = sapply(AGES, function(a) cens(p, s, a)))))))
write.csv(ages, "diaspora_ages.csv", row.names = FALSE)
# Agrégats régionaux : pays dont au plus deux groupes d'âge sont au plancher
REGION <- c(setNames(rep("Europe et Amérique du Nord", 13), c("FR", "BE", "GB", "DE", "NL", "CH", "IT", "ES", "SE", "IE", "PT", "US", "CA")),
            setNames(rep("Afrique", 11), c("ZA", "AO", "ZM", "UG", "RW", "BI", "TZ", "KE", "SS", "CG", "CF")), AE = "Asie occidentale")
ok <- names(which(tapply(ages$plancher, ages$pays, sum) <= 2))
ag <- aggregate(effectif ~ region + sexe + ages, data = transform(ages[ages$pays %in% ok, ], region = REGION[pays]), sum)
ag$pct <- 100 * ag$effectif / ave(ag$effectif, ag$region, FUN = sum)
write.csv(ag, "diaspora_ages_regions.csv", row.names = FALSE)
# Part des femmes selon Meta (figure 4) : pays où les deux sexes dépassent le plancher
sx <- tab[!tab$cens_sexe, ]
cat("Part des femmes (Meta) : ensemble", round(100 * sum(sx$meta_f) / sum(sx$meta_t), 1), "%\n")
print(ag[ag$region != "Asie occidentale", ], row.names = FALSE)

# --- Tendances des Nations unies 1990-2024 (figure 6) ------------------------------------------------------
tend <- do.call(rbind, lapply(c(pays, "MONDE"), function(p) {
  code <- if (p == "MONDE") 900 else M49[[p]]
  r <- rdc[rdc[[5]] == code, ]
  if (!nrow(r)) return(NULL)
  data.frame(pays = p, annee = ANNEES, total = as.numeric(r[1, 8:15]), hommes = as.numeric(r[1, 16:23]),
             femmes = as.numeric(r[1, 24:31]))
}))
tend$pct_femmes <- ifelse(tend$total > 0, 100 * tend$femmes / tend$total, NA)   # Nations unies, pour information
write.csv(tend, "diaspora_tendances.csv", row.names = FALSE)

# --- Résumé ------------------------------------------------------------------------------------
com <- tab[!is.na(tab$onu_t), ]
cat("Dix premières destinations (max Meta, ONU) :", paste(head(tab$nom, 10), collapse = ", "), "\n")
cat("Pays communs :", nrow(com), "| Meta", sum(com$meta_t), "| ONU", sum(com$onu_t), "\n")
cat("Spearman :", round(cor(com$meta_t, com$onu_t, method = "spearman"), 3),
    "| Pearson (log) :", round(cor(log(com$meta_t), log(com$onu_t)), 3), "\n")
print(tab[, c("nom", "meta_t", "onu_t", "rapport", "pct_f_meta", "pct_f_onu")], row.names = FALSE)
