/**
 * Utilitários para autenticação e criptografia
 * Usando Web Crypto API para criptografia segura
 */

/**
 * Gera um hash seguro de senha usando PBKDF2
 */
export async function hashPassword(password: string): Promise<string> {
  const encoder = new TextEncoder();
  const data = encoder.encode(password);
  
  // Gerar salt aleatório
  const salt = crypto.getRandomValues(new Uint8Array(16));
  
  // Importar a senha como chave
  const keyMaterial = await crypto.subtle.importKey(
    "raw",
    data,
    "PBKDF2",
    false,
    ["deriveBits"]
  );
  
  // Derivar a chave usando PBKDF2
  const derivedBits = await crypto.subtle.deriveBits(
    {
      name: "PBKDF2",
      salt: salt,
      iterations: 100000,
      hash: "SHA-256",
    },
    keyMaterial,
    256
  );
  
  // Combinar salt + hash
  const hashArray = new Uint8Array(derivedBits);
  const combined = new Uint8Array(salt.length + hashArray.length);
  combined.set(salt);
  combined.set(hashArray, salt.length);
  
  // Converter para base64
  return btoa(String.fromCharCode(...combined));
}

/**
 * Verifica se uma senha corresponde ao hash
 */
export async function verifyPassword(
  password: string,
  hash: string
): Promise<boolean> {
  try {
    // Decodificar o hash de base64
    const combined = Uint8Array.from(atob(hash), (c) => c.charCodeAt(0));
    
    // Extrair salt e hash
    const salt = combined.slice(0, 16);
    const storedHash = combined.slice(16);
    
    // Gerar hash da senha fornecida
    const encoder = new TextEncoder();
    const data = encoder.encode(password);
    
    const keyMaterial = await crypto.subtle.importKey(
      "raw",
      data,
      "PBKDF2",
      false,
      ["deriveBits"]
    );
    
    const derivedBits = await crypto.subtle.deriveBits(
      {
        name: "PBKDF2",
        salt: salt,
        iterations: 100000,
        hash: "SHA-256",
      },
      keyMaterial,
      256
    );
    
    const newHash = new Uint8Array(derivedBits);
    
    // Comparar os hashes
    if (newHash.length !== storedHash.length) {
      return false;
    }
    
    for (let i = 0; i < newHash.length; i++) {
      if (newHash[i] !== storedHash[i]) {
        return false;
      }
    }
    
    return true;
  } catch (error) {
    console.error("Erro ao verificar senha:", error);
    return false;
  }
}

/**
 * Gera um token aleatório seguro
 */
export function generateToken(): string {
  const array = new Uint8Array(32);
  crypto.getRandomValues(array);
  return btoa(String.fromCharCode(...array))
    .replace(/\+/g, "-")
    .replace(/\//g, "_")
    .replace(/=/g, "");
}

/**
 * Valida formato de matrícula (apenas números)
 */
export function validarMatricula(matricula: string): boolean {
  return /^\d+$/.test(matricula) && matricula.length >= 3;
}

/**
 * Valida formato de senha (alfanuméricos e símbolos)
 */
export function validarSenha(senha: string): boolean {
  // Mínimo 8 caracteres, pelo menos uma letra, um número e um símbolo
  const regex = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/;
  return regex.test(senha);
}

/**
 * Criptografia reversível para senhas SMTP usando AES-GCM
 * NOTA: Esta função é usada apenas para senhas SMTP que precisam ser descriptografadas.
 * Para senhas de usuários, use hashPassword() que é unidirecional.
 */

// Chave de criptografia derivada (em produção, deve vir de variável de ambiente)
// Para desenvolvimento, usando uma chave fixa. Em produção, deve ser configurada via env var.
const getEncryptionKey = async (): Promise<CryptoKey> => {
  // Chave base - em produção, isso deve vir de process.env.ENCRYPTION_KEY
  // Por enquanto, usando uma chave derivada de um valor fixo
  const keyMaterial = new TextEncoder().encode("SGSE-EMAIL-ENCRYPTION-KEY-2024");
  
  // Deriva uma chave de 256 bits usando PBKDF2
  const key = await crypto.subtle.importKey(
    "raw",
    keyMaterial,
    { name: "PBKDF2" },
    false,
    ["deriveBits", "deriveKey"]
  );

  return await crypto.subtle.deriveKey(
    {
      name: "PBKDF2",
      salt: new TextEncoder().encode("SGSE-SALT"),
      iterations: 100000,
      hash: "SHA-256",
    },
    key,
    { name: "AES-GCM", length: 256 },
    false,
    ["encrypt", "decrypt"]
  );
};

/**
 * Criptografa uma senha SMTP usando AES-GCM
 */
export async function encryptSMTPPassword(password: string): Promise<string> {
  try {
    const key = await getEncryptionKey();
    const encoder = new TextEncoder();
    const data = encoder.encode(password);

    // Gerar IV (Initialization Vector) aleatório
    const iv = crypto.getRandomValues(new Uint8Array(12));

    // Criptografar
    const encrypted = await crypto.subtle.encrypt(
      {
        name: "AES-GCM",
        iv: iv,
      },
      key,
      data
    );

    // Combinar IV + dados criptografados e converter para base64
    const combined = new Uint8Array(iv.length + encrypted.byteLength);
    combined.set(iv);
    combined.set(new Uint8Array(encrypted), iv.length);

    return btoa(String.fromCharCode(...combined));
  } catch (error) {
    console.error("Erro ao criptografar senha SMTP:", error);
    throw new Error("Falha ao criptografar senha SMTP");
  }
}

/**
 * Descriptografa uma senha SMTP usando AES-GCM
 */
export async function decryptSMTPPassword(encryptedPassword: string): Promise<string> {
  try {
    const key = await getEncryptionKey();
    
    // Decodificar base64
    const combined = Uint8Array.from(atob(encryptedPassword), (c) => c.charCodeAt(0));

    // Extrair IV e dados criptografados
    const iv = combined.slice(0, 12);
    const encrypted = combined.slice(12);

    // Descriptografar
    const decrypted = await crypto.subtle.decrypt(
      {
        name: "AES-GCM",
        iv: iv,
      },
      key,
      encrypted
    );

    // Converter para string
    const decoder = new TextDecoder();
    return decoder.decode(decrypted);
  } catch (error) {
    console.error("Erro ao descriptografar senha SMTP:", error);
    throw new Error("Falha ao descriptografar senha SMTP");
  }
}

