package dev.lions.controllers;

import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.RequestScoped;
import jakarta.enterprise.event.Event;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import dev.lions.config.ApplicationConfig;
import dev.lions.events.AnalyticsEvent;
import dev.lions.services.ProjectService;
import dev.lions.exceptions.InitializationException;

import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

/**
 * Contrôleur de la page d'index.
 * Gère l'affichage et les interactions de la page d'accueil principale
 * en assurant le chargement des messages localisés et des données nécessaires.
 */
@Slf4j
@Named
@RequestScoped
public class IndexController {

  private static final String BUNDLE_NAME = "messages";
  private static final String DEFAULT_LOCALE = "fr";

  @Inject
  ApplicationConfig applicationConfig;

  @Inject
  ProjectService projectService;

  @Inject
  Event<AnalyticsEvent> analyticsEvent;

  @Getter
  private String welcomeMessage;

  @Getter
  private String applicationName;

  @Getter
  private String environment;

  @Getter @Setter
  private String message;

  private ResourceBundle messageBundle;

  @PostConstruct
  public void init() {
    log.info("Initialisation du contrôleur Index");
    try {
      initializeMessageBundle();
      initializeApplicationSettings();
      notifyPageView();
      log.info("Contrôleur Index initialisé avec succès");
    } catch (Exception e) {
      String errorMessage = "Erreur lors de l'initialisation du contrôleur Index";
      log.error(errorMessage, e);
      throw new InitializationException(errorMessage, e);
    }
  }

  /**
   * Récupère un message localisé avec une clé donnée.
   * La méthode est maintenant protégée pour permettre l'interception par CDI
   */
  protected String getMessage(@NotNull String key) {
    try {
      return messageBundle.getString(key);
    } catch (Exception e) {
      log.warn("Message non trouvé pour la clé: {}", key);
      return key;
    }
  }

  /**
   * Vérifie si l'environnement est en mode développement.
   */
  public boolean isDevelopmentMode() {
    return applicationConfig.isDevelopment();
  }

  /**
   * Récupère le nombre total de projets.
   */
  public long getProjectCount() {
    try {
      return projectService.getProjectCount();
    } catch (Exception e) {
      log.warn("Erreur lors de la récupération du nombre de projets", e);
      return 0;
    }
  }

  /**
   * Retourne un message de statut pour le mode développement.
   */
  public String getStatusMessage() {
    if (isDevelopmentMode()) {
      return String.format("Mode développement - Environnement: %s", environment);
    }
    return "";
  }

  /**
   * Recharge les messages et paramètres du contrôleur.
   */
  public void refresh() {
    log.info("Rafraîchissement des données du contrôleur Index");
    initializeMessageBundle();
    initializeApplicationSettings();
    notifyPageView();
  }

  /**
   * Initialise le bundle de messages localisés.
   */
  protected void initializeMessageBundle() {
    log.debug("Chargement des messages localisés");
    Locale locale = new Locale(DEFAULT_LOCALE);
    messageBundle = ResourceBundle.getBundle(BUNDLE_NAME, locale);

    welcomeMessage = getMessage("welcome.message");
    message = String.format("%s - %s",
                            getMessage("index.greeting"),
                            applicationConfig.getApplicationName());

    log.debug("Messages localisés chargés avec succès");
  }

  /**
   * Initialise les paramètres de l'application.
   */
  protected void initializeApplicationSettings() {
    log.debug("Chargement des paramètres de l'application");
    applicationName = applicationConfig.getApplicationName();
    environment = applicationConfig.getEnvironment();
    log.debug("Paramètres de l'application chargés : env={}", environment);
  }

  /**
   * Notifie le système d'une vue de page.
   */
  protected void notifyPageView() {
    analyticsEvent.fire(AnalyticsEvent.builder()
                                      .eventType("PAGE_VIEW")
                                      .properties(Map.of(
                                          "page", "index",
                                          "environment", environment,
                                          "timestamp", System.currentTimeMillis()
                                      ))
                                      .build());
  }
}