package dev.lions.utils;

import jakarta.enterprise.context.ApplicationScoped;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * Utilitaire pour des opérations de sécurité sur les fichiers, notamment
 * la sécurisation des noms de fichiers et l'initialisation des paramètres de chiffrement.
 */
@ApplicationScoped
@Slf4j
public class SecurityUtils {

  private SecretKey encryptionKey;

  /**
   * Nettoie et sécurise un nom de fichier pour éviter les vulnérabilités.
   *
   * @param fileName Le nom de fichier original
   * @return Nom de fichier sécurisé
   */
  public String sanitizeFileName(String fileName) {
    return fileName.replaceAll("[^a-zA-Z0-9\\.\\-]", "_");
  }

  /**
   * Initialise le chiffrement en générant une clé secrète.
   * Cette méthode est utilisée pour configurer les paramètres
   * de sécurité avant toute opération de stockage.
   */
  public void initializeEncryption() {
    try {
      log.info("Initialisation du chiffrement sécurisé");

      KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
      keyGenerator.init(256); // Clé de 256 bits
      encryptionKey = keyGenerator.generateKey();

      log.info("Clé de chiffrement initialisée avec succès");

    } catch (NoSuchAlgorithmException e) {
      log.error("Erreur lors de l'initialisation du chiffrement", e);
      throw new SecurityException("Impossible d'initialiser le chiffrement", e);
    }
  }

  /**
   * Chiffre une donnée texte avec la clé générée.
   *
   * @param plainText Donnée en clair
   * @return Donnée chiffrée en base64
   */
  public String encryptData(String plainText) {
    try {
      Cipher cipher = Cipher.getInstance("AES");
      cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);

      byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
      return Base64.getEncoder().encodeToString(encryptedBytes);

    } catch (Exception e) {
      log.error("Erreur lors du chiffrement des données", e);
      throw new SecurityException("Erreur lors du chiffrement des données", e);
    }
  }

  /**
   * Déchiffre une donnée texte en base64 avec la clé générée.
   *
   * @param encryptedText Donnée chiffrée en base64
   * @return Donnée en clair
   */
  public String decryptData(String encryptedText) {
    try {
      Cipher cipher = Cipher.getInstance("AES");
      cipher.init(Cipher.DECRYPT_MODE, encryptionKey);

      byte[] decodedBytes = Base64.getDecoder().decode(encryptedText);
      byte[] decryptedBytes = cipher.doFinal(decodedBytes);

      return new String(decryptedBytes);

    } catch (Exception e) {
      log.error("Erreur lors du déchiffrement des données", e);
      throw new SecurityException("Erreur lors du déchiffrement des données", e);
    }
  }

  /**
   * Vérifie si le chiffrement a été initialisé.
   *
   * @return true si la clé de chiffrement est initialisée
   */
  public boolean isEncryptionInitialized() {
    return encryptionKey != null;
  }
}
