mixte_model_function <- function(var_expliquee,var_explicatives_fixes,var_explicatives_alea,data) {
  tryCatch({
    form_alea = as.formula(paste0("~1 |",paste(var_explicatives_alea,collapse="/")))
    form_fix = paste(var_explicatives_fixes,collapse="*")
    form = as.formula(paste(var_expliquee,form_fix,collapse="~"))
    model <-  lme(form, random=form_alea, data=data)
    return(model)
  },
  error = function(e) {
    message('An Error Occurred')
    cat("Erreur :", conditionMessage(e), "\n")
    traceback()
    return(NULL)
  })
    
}

mixte_table_function <- function(var_expliquee,var_explicatives_fixes,var_explicatives_alea,data) {
  tryCatch({
    form_alea = as.formula(paste0("~1 |",paste(var_explicatives_alea,collapse="/")))
    form_fix = paste(var_explicatives_fixes,collapse="*")
    form = as.formula(paste(var_expliquee,form_fix,collapse="~"))
    model =  lme(form, random=form_alea, data=data)
    return(as.data.frame(emmeans(model,specs=var_explicatives_fixes)))
  },
  error = function(e) {
    message('An Error Occurred')
    cat("Erreur :", conditionMessage(e), "\n")
    traceback()
    return(NULL)
  })
    
}

#Que veut on afficher ? variance + varident + matrice variance-covariance (regarde varcor)

mixte_graph <- function(model,effets, output) {
  tryCatch({
    
    graphs <- hypothesisGraph(model, effets = effets, export = F)
  
    # Créer un plotly pour chaque graphique
    for (i in seq_along(graphs)) {
      local({
        local_i <- i
        local_name <- names(graphs)[local_i]
        output[[paste0("hypothesisGraph", local_i)]] <- renderPlotly({
          ggplotly(graphs[[local_i]]) %>%
            layout(title = local_name, autosize = TRUE)
        })
      })
    }
    
    # Retourner les noms des sorties pour l'UI
    return(paste0("hypothesisGraph", seq_along(graphs)))
  },
  error = function(e) {
    message('An Error Occurred')
    cat("Erreur :", conditionMessage(e), "\n")
    traceback()
    return(NULL)
  })

  
}

get_Rsquared = function(mod){
  updated_mod = update(mod, fixed=Valeur~Produit * Temps + Humidite + Temperature)
  R2_x = MuMIn::r.squaredGLMM(mod)[2] - MuMIn::r.squaredGLMM(updated_mod)[2]
  return(abs(R2_x))
}

compare_lmm <- function(model1,model2) {
    comp <- anova(model1,model2)
    return(comp)
}

mixte_model_anova <- function(mod) {
  return(data.frame(Anova(mod,type=3)))
}

mixte_model_comparaison <- function(mod_list) {  
  n <- length(mod_list)
  
  results <- data.frame(
    Model1 = character(),
    Model2 = character(),
    logLik1 = numeric(),
    logLik2 = numeric(),
    L.Ratio = numeric(),
    p.value = numeric(),
    stringsAsFactors = FALSE
  )
  model_names <- names(mod_list)
  
  for (i in 1:(n - 1)) {
    for (j in (i + 1):n) {
      model1 <- mod_list[[model_names[i]]]
      model2 <- mod_list[[model_names[j]]]
      anova_result <- anova(model1, model2)
      print(model1)
      print(model2)
      print(anova_result)
      logLik1 <- logLik(model1)
      logLik2 <- logLik(model2)
      L.Ratio <- anova_result$L.Ratio[2]
      p.value <- anova_result$`p-value`[2]
      if ("p-value" %in% names(anova_result)) {
        p.value <- anova_result$`p-value`[2]
        L.Ratio <- anova_result$L.Ratio[2]
        }
        else {
          p.value <- 0
          L.Ratio <- 0
        }
      results <- rbind(results, data.frame(
        Model1 = model_names[i],
        Model2 = model_names[j],
        logLik1 = as.numeric(logLik1),
        logLik2 = as.numeric(logLik2),
        L.Ratio = L.Ratio,
        p.value = p.value,
        stringsAsFactors = FALSE
      ))
    }
  }
  
  colnames(results) <- c("Model 1", "Model 2", "Log Likelihood 1", "Log Likelihood 2", "Likelihood Ratio", "P-value")
  return(results)
}

mixte_emmeans_function <- function(mod, var_explicatives) {
  tryCatch({
    # Construction de la formule pour emmeans
    formule_emmeans <- as.formula(paste0("~", paste(var_explicatives, collapse = "*")))

    # Calculer les moyennes marginales estimées (emmeans)
    emm <- emmeans(mod, formule_emmeans)
    
    return(emm)
    
  }, warning = function(w) {
    warning("Avertissement rencontré : ", conditionMessage(w))
    return(NULL)
  }, error = function(e) {
    message("Erreur : ", conditionMessage(e))
    return(NULL)
  })
}


mixte_emmeans_function_table <- function(mod, type_comp,output,var_explicatives) {
  tryCatch({

    # Créer les formules
    if (type_comp == 'trt.vs.ctrl') {
      structure_formule = as.formula(paste0("trt.vs.ctrl~",paste(var_explicatives,collapse = "*")))
      emm <- emmeans(mod, structure_formule)$emmeans
    } else if (type_comp == 'pairwise') {
      structure_formule = as.formula(paste0("pairwise~",paste(var_explicatives,collapse = "*")))
      emm <- emmeans(mod, structure_formule)$emmeans
    } else if (type_comp == 'personnalisé') {
      structure_formule = as.formula(paste0("~",paste(var_explicatives,collapse = "*")))
      emm <- emmeans(mod, specs=var_explicatives)
    }  
    # Convertir en tableau de données et arrondir
    emmeans_table <- as.data.frame(emm)
    
    for (col in names(emmeans_table)) {
      if (is.numeric(emmeans_table[[col]])) {
        emmeans_table[[col]] <- round(emmeans_table[[col]], 3)
      }
    }
    
    emmeans_table <- na.omit(emmeans_table)
    output$mixte_graph_compared_mean <- renderPlotly({
      return(comparisonGraph(emmeansObj = emm))
    })
    output$mixte_emmeans_result <- renderPrint({
      return(emm)
    })
    return(emmeans_table)
    
  }, warning = function(w) {
    warning("Avertissement rencontré : ", conditionMessage(w))
    return(NULL)
  }, error = function(e) {
    message("Erreur rencontrée (mixte_emmeans_function_table) : ", conditionMessage(e))
    return(NULL)
  })
}

mixte_contrast_function <- function(emm,ref1,ref2){

  tryCatch({


      #On réccupère ensuite les différents niveaux possibles
      ref_list <- contrast_list_function(emm)

      #On initialise nos vecteurs
      contrast1 <- rep(0,length(ref_list))
      contrast2 <- rep(0,length(ref_list))
      for (ref in ref1) {
        ind <- which(ref_list == ref)
        contrast1[ind] = 1
      }
      for (ref in ref2) {
        ind <- which(ref_list == ref)
        contrast2[ind] = -1
      }
      cont <- contrast1+contrast2
      return(cont)
  },
  error = function(e) {
    message('An Error Occurred')
    cat("Erreur :", conditionMessage(e), "\n")
    traceback()
    return(NULL)
  },
  warning = function(w) {
    message('A Warning Occured')
    print(w)
    return(a)
  })

  
}

mixte_contrasts_table_function <- function(mod, type_comp,ref_index,contrast_list) {
  tryCatch({

    # Calculer les contrastes
    if (type_comp == 'trt.vs.ctrl') {
        contr <- contrast(mod, type_comp, ref = ref_index)
    } else if (type_comp == "pairwise") {
        contr <- contrast(mod, type_comp)
    } else if (type_comp == "personnalisé") {
      list_contrasts <- contrast_list
      contr <- contrast(mod, method=list_contrasts)
    }
    
    # Convertir en tableau de données et arrondir
    emmeans_table <- as.data.frame(contr)
    
    for (col in names(emmeans_table)) {
      if (is.numeric(emmeans_table[[col]])) {
        emmeans_table[[col]] <- round(emmeans_table[[col]], 3)
      }
    }
    
    emmeans_table <- na.omit(emmeans_table)
    return(emmeans_table)
    
  }, warning = function(w) {
    warning("Avertissement rencontré : ", conditionMessage(w))
    return(NULL)
  }, error = function(e) {
    message("Erreur rencontrée (mixte_contrasts_table_function) : ", conditionMessage(e))
    return(NULL)
  })
}