data {
  int<lower=1> T;
  array[T] int<lower=0> y_I;
  array[T] int<lower=0> y_C;
  vector[T] log_exposure50;

  int<lower=0> P_pi_I;
  int<lower=0> P_mu_I;
  int<lower=0> P_pi_C;
  int<lower=0> P_mu_C;

  matrix[T, P_pi_I] X_pi_I;
  matrix[T, P_mu_I] X_mu_I;
  matrix[T, P_pi_C] X_pi_C;
  matrix[T, P_mu_C] X_mu_C;

  real<lower=0> hs_tau0;
  real<lower=0> hs_slab_scale;
  real<lower=2> hs_slab_df;
}
transformed data {
  real FLOOR = -1e6; // castigo numérico estable

  // int no admite constraints en Stan
  array[T] int z_I;
  array[T] int z_C;
  for (t in 1:T) {
    z_I[t] = y_I[t] > 0;
    z_C[t] = y_C[t] > 0;
  }
  real<lower=0> c2 = square(hs_slab_scale) * hs_slab_df / (hs_slab_df - 2);
}
parameters {
  real a_pi_I; real a_mu_I;
  real a_pi_C; real a_mu_C;

  real<lower=0> tau_pi_I;
  real<lower=0> tau_mu_I;
  real<lower=0> tau_pi_C;
  real<lower=0> tau_mu_C;

  vector[P_pi_I] z_pi_I;
  vector<lower=0>[P_pi_I] lambda_pi_I;
  vector[P_mu_I] z_mu_I;
  vector<lower=0>[P_mu_I] lambda_mu_I;

  vector[P_pi_C] z_pi_C;
  vector<lower=0>[P_pi_C] lambda_pi_C;
  vector[P_mu_C] z_mu_C;
  vector<lower=0>[P_mu_C] lambda_mu_C;

  real log_phi_I;
  real log_phi_C;
}
transformed parameters {
  vector[P_pi_I] b_pi_I;
  vector[P_mu_I] b_mu_I;
  vector[P_pi_C] b_pi_C;
  vector[P_mu_C] b_mu_C;

  if (P_pi_I > 0) {
    for (j in 1:P_pi_I) {
      real tau_til = hs_tau0 * tau_pi_I * lambda_pi_I[j]
                     * sqrt(c2 / (c2 + square(hs_tau0 * tau_pi_I * lambda_pi_I[j])));
      b_pi_I[j] = z_pi_I[j] * tau_til;
    }
  }
  if (P_mu_I > 0) {
    for (j in 1:P_mu_I) {
      real tau_til = hs_tau0 * tau_mu_I * lambda_mu_I[j]
                     * sqrt(c2 / (c2 + square(hs_tau0 * tau_mu_I * lambda_mu_I[j])));
      b_mu_I[j] = z_mu_I[j] * tau_til;
    }
  }
  if (P_pi_C > 0) {
    for (j in 1:P_pi_C) {
      real tau_til = hs_tau0 * tau_pi_C * lambda_pi_C[j]
                     * sqrt(c2 / (c2 + square(hs_tau0 * tau_pi_C * lambda_pi_C[j])));
      b_pi_C[j] = z_pi_C[j] * tau_til;
    }
  }
  if (P_mu_C > 0) {
    for (j in 1:P_mu_C) {
      real tau_til = hs_tau0 * tau_mu_C * lambda_mu_C[j]
                     * sqrt(c2 / (c2 + square(hs_tau0 * tau_mu_C * lambda_mu_C[j])));
      b_mu_C[j] = z_mu_C[j] * tau_til;
    }
  }
}
model {
  // Priors
  a_pi_I ~ normal(0, 2);
  a_pi_C ~ normal(0, 2);
  a_mu_I ~ normal(0, 1);
  a_mu_C ~ normal(0, 1);

  tau_pi_I ~ cauchy(0, 1);
  tau_mu_I ~ cauchy(0, 1);
  tau_pi_C ~ cauchy(0, 1);
  tau_mu_C ~ cauchy(0, 1);

  if (P_pi_I > 0) { z_pi_I ~ normal(0, 1); lambda_pi_I ~ cauchy(0, 1); }
  if (P_mu_I > 0) { z_mu_I ~ normal(0, 1); lambda_mu_I ~ cauchy(0, 1); }
  if (P_pi_C > 0) { z_pi_C ~ normal(0, 1); lambda_pi_C ~ cauchy(0, 1); }
  if (P_mu_C > 0) { z_mu_C ~ normal(0, 1); lambda_mu_C ~ cauchy(0, 1); }

  log_phi_I ~ normal(0, 1) T[-5, 5];
  log_phi_C ~ normal(0, 1) T[-5, 5];

  // etas con ramas P=0 seguras
  vector[T] eta_pi_I;
  vector[T] eta_pi_C;
  vector[T] eta_mu_I;
  vector[T] eta_mu_C;

  if (P_pi_I > 0) eta_pi_I = a_pi_I + X_pi_I * b_pi_I;
  else            eta_pi_I = rep_vector(a_pi_I, T);

  if (P_pi_C > 0) eta_pi_C = a_pi_C + X_pi_C * b_pi_C;
  else            eta_pi_C = rep_vector(a_pi_C, T);

  if (P_mu_I > 0) eta_mu_I = a_mu_I + X_mu_I * b_mu_I + log_exposure50;
  else            eta_mu_I = rep_vector(a_mu_I, T) + log_exposure50;

  if (P_mu_C > 0) eta_mu_C = a_mu_C + X_mu_C * b_mu_C + log_exposure50;
  else            eta_mu_C = rep_vector(a_mu_C, T) + log_exposure50;

  real phi_I = exp(fmin(log_phi_I, 10));
  real phi_C = exp(fmin(log_phi_C, 10));

  for (t in 1:T) {
    // clamps numéricos
    real eta_pi_I_safe = fmin(fmax(eta_pi_I[t], -15), 15);
    real eta_pi_C_safe = fmin(fmax(eta_pi_C[t], -15), 15);
    real pi_I = inv_logit(eta_pi_I_safe);
    real pi_C = inv_logit(eta_pi_C_safe);

    real eta_mu_I_safe = fmin(fmax(eta_mu_I[t], -20), 20);
    real eta_mu_C_safe = fmin(fmax(eta_mu_C[t], -20), 20);

    if (y_I[t] == 0) {
      target += log1m(pi_I);
    } else {
      real log_p0_I = neg_binomial_2_log_lpmf(0 | eta_mu_I_safe, phi_I);
      // portable: NaN o >=0 cae aquí; -inf y <0 son válidos
      if (!(log_p0_I < 0)) {
        target += FLOOR;
      } else {
        target += log(pi_I)
                + neg_binomial_2_log_lpmf(y_I[t] | eta_mu_I_safe, phi_I)
                - log1m_exp(log_p0_I);
      }
    }

    if (y_C[t] == 0) {
      target += log1m(pi_C);
    } else {
      real log_p0_C = neg_binomial_2_log_lpmf(0 | eta_mu_C_safe, phi_C);
      if (!(log_p0_C < 0)) {
        target += FLOOR;
      } else {
        target += log(pi_C)
                + neg_binomial_2_log_lpmf(y_C[t] | eta_mu_C_safe, phi_C)
                - log1m_exp(log_p0_C);
      }
    }
  }
}
generated quantities {
  vector[T] pi_I;
  vector[T] pi_C;
  vector[T] mu_I;
  vector[T] mu_C;

  array[T] int y_I_rep;
  array[T] int y_C_rep;

  vector[T] log_lik_I;
  vector[T] log_lik_C;
  vector[T] log_lik_joint;

  vector[T] eta_pi_I;
  vector[T] eta_pi_C;
  vector[T] eta_mu_I;
  vector[T] eta_mu_C;

  real phi_I = exp(fmin(log_phi_I, 10));
  real phi_C = exp(fmin(log_phi_C, 10));

  if (P_pi_I > 0) eta_pi_I = a_pi_I + X_pi_I * b_pi_I;
  else            eta_pi_I = rep_vector(a_pi_I, T);

  if (P_pi_C > 0) eta_pi_C = a_pi_C + X_pi_C * b_pi_C;
  else            eta_pi_C = rep_vector(a_pi_C, T);

  if (P_mu_I > 0) eta_mu_I = a_mu_I + X_mu_I * b_mu_I + log_exposure50;
  else            eta_mu_I = rep_vector(a_mu_I, T) + log_exposure50;

  if (P_mu_C > 0) eta_mu_C = a_mu_C + X_mu_C * b_mu_C + log_exposure50;
  else            eta_mu_C = rep_vector(a_mu_C, T) + log_exposure50;

  for (t in 1:T) {
    real eta_pi_I_safe = fmin(fmax(eta_pi_I[t], -15), 15);
    real eta_pi_C_safe = fmin(fmax(eta_pi_C[t], -15), 15);
    pi_I[t] = inv_logit(eta_pi_I_safe);
    pi_C[t] = inv_logit(eta_pi_C_safe);

    real eta_mu_I_safe = fmin(fmax(eta_mu_I[t], -20), 20);
    real eta_mu_C_safe = fmin(fmax(eta_mu_C[t], -20), 20);

    mu_I[t] = exp(eta_mu_I_safe);
    mu_C[t] = exp(eta_mu_C_safe);

    // réplicas
    int z_rep_I = bernoulli_rng(pi_I[t]);
    int z_rep_C = bernoulli_rng(pi_C[t]);

    if (z_rep_I == 0) y_I_rep[t] = 0;
    else {
      int raw_I = neg_binomial_2_log_rng(eta_mu_I_safe, phi_I);
      y_I_rep[t] = raw_I > 0 ? raw_I : 1;
    }

    if (z_rep_C == 0) y_C_rep[t] = 0;
    else {
      int raw_C = neg_binomial_2_log_rng(eta_mu_C_safe, phi_C);
      y_C_rep[t] = raw_C > 0 ? raw_C : 1;
    }

    // log-lik
    if (y_I[t] == 0) {
      log_lik_I[t] = log1m(pi_I[t]);
    } else {
      real log_p0_I = neg_binomial_2_log_lpmf(0 | eta_mu_I_safe, phi_I);
      if (!(log_p0_I < 0)) {
        log_lik_I[t] = FLOOR;
      } else {
        log_lik_I[t] = log(pi_I[t])
                     + neg_binomial_2_log_lpmf(y_I[t] | eta_mu_I_safe, phi_I)
                     - log1m_exp(log_p0_I);
      }
    }

    if (y_C[t] == 0) {
      log_lik_C[t] = log1m(pi_C[t]);
    } else {
      real log_p0_C = neg_binomial_2_log_lpmf(0 | eta_mu_C_safe, phi_C);
      if (!(log_p0_C < 0)) {
        log_lik_C[t] = FLOOR;
      } else {
        log_lik_C[t] = log(pi_C[t])
                     + neg_binomial_2_log_lpmf(y_C[t] | eta_mu_C_safe, phi_C)
                     - log1m_exp(log_p0_C);
      }
    }

    log_lik_joint[t] = log_lik_I[t] + log_lik_C[t];
  }
}
