package com.social.media;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.crypto.password.PasswordEncoder;

import static org.junit.jupiter.api.Assertions.*;

/**
 * Teste simples para demonstrar criptografia e verificação de senhas
 * com a senha: Leader@2025!Strong#Pass
 */
@SpringBootTest
public class PasswordHashTest {
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    private static final String TEST_PASSWORD = "Leader@2025!Strong#Pass";
    
    @Test
    public void testPasswordEncryptionAndVerification() {
        System.out.println("\n=== DEMONSTRAÇÃO COMPLETA DE CRIPTOGRAFIA DE SENHA ===");
        System.out.println("Senha original: " + TEST_PASSWORD);
        
        // 1. Demonstrar o processo de registro (criptografia)
        demonstratePasswordRegistration();
        
        // 2. Demonstrar o processo de login (verificação)
        demonstratePasswordLogin();
        
        // 3. Demonstrar tentativa de login com senha incorreta
        demonstrateFailedLogin();
        
        // 4. Demonstrar diferentes hashes para a mesma senha
        demonstrateBCryptSalting();
        
        System.out.println("\n✅ DEMONSTRAÇÃO CONCLUÍDA COM SUCESSO!");
        System.out.println("A senha '" + TEST_PASSWORD + "' foi processada corretamente.");
    }
    
    private void demonstratePasswordRegistration() {
        System.out.println("\n=== 1. PROCESSO DE REGISTRO (CRIPTOGRAFIA) ===");
        
        // Simular o que acontece quando um usuário se registra
        System.out.println("🔐 Usuário se registra com senha: " + TEST_PASSWORD);
        
        // Gerar hash da senha (o que seria salvo no banco)
        String hashedPassword = passwordEncoder.encode(TEST_PASSWORD);
        System.out.println("🔒 Hash gerado (salvo no banco): " + hashedPassword);
        
        // Verificar que o hash é diferente da senha original
        assertNotEquals(TEST_PASSWORD, hashedPassword, 
                       "Hash deve ser diferente da senha original");
        
        // Verificar que o hash pode ser usado para verificação
        boolean canVerify = passwordEncoder.matches(TEST_PASSWORD, hashedPassword);
        assertTrue(canVerify, "Hash deve permitir verificação da senha original");
        
        System.out.println("✅ Senha criptografada e pronta para armazenamento");
        System.out.println("💡 Observação: A senha original NUNCA é armazenada!");
    }
    
    private void demonstratePasswordLogin() {
        System.out.println("\n=== 2. PROCESSO DE LOGIN (VERIFICAÇÃO) ===");
        
        // Simular hash que estaria salvo no banco (de um registro anterior)
        String storedHash = passwordEncoder.encode(TEST_PASSWORD);
        System.out.println("🗃️  Hash recuperado do banco: " + storedHash);
        
        // Simular usuário tentando fazer login
        String userInputPassword = TEST_PASSWORD;
        System.out.println("👤 Usuário tenta login com senha: " + userInputPassword);
        
        // Verificar se a senha fornecida pelo usuário confere com o hash
        boolean loginSuccessful = passwordEncoder.matches(userInputPassword, storedHash);
        System.out.println("🔍 Verificação BCrypt: " + (loginSuccessful ? "SUCESSO" : "FALHA"));
        
        assertTrue(loginSuccessful, "Login deve ser bem-sucedido com senha correta");
        
        System.out.println("✅ Login autorizado - usuário autenticado!");
    }
    
    private void demonstrateFailedLogin() {
        System.out.println("\n=== 3. TENTATIVA DE LOGIN COM SENHA INCORRETA ===");
        
        // Hash correto (simulando o que está no banco)
        String storedHash = passwordEncoder.encode(TEST_PASSWORD);
        System.out.println("🗃️  Hash correto no banco: " + storedHash);
        
        // Usuário tenta com senha incorreta
        String wrongPassword = "SenhaIncorreta123!";
        System.out.println("👤 Usuário tenta login com senha incorreta: " + wrongPassword);
        
        // Verificar que a senha incorreta falha
        boolean loginFailed = passwordEncoder.matches(wrongPassword, storedHash);
        System.out.println("🔍 Verificação BCrypt: " + (loginFailed ? "SUCESSO" : "FALHA"));
        
        assertFalse(loginFailed, "Login deve falhar com senha incorreta");
        
        System.out.println("❌ Login negado - senha incorreta!");
        System.out.println("🛡️  Sistema protegido contra tentativas de invasão");
    }
    
    private void demonstrateBCryptSalting() {
        System.out.println("\n=== 4. DEMONSTRAÇÃO DO SALT ÚNICO DO BCRYPT ===");
        System.out.println("💡 Mesmo com a mesma senha, o BCrypt gera hashes diferentes:");
        
        for (int i = 1; i <= 5; i++) {
            String hash = passwordEncoder.encode(TEST_PASSWORD);
            boolean verifies = passwordEncoder.matches(TEST_PASSWORD, hash);
            
            System.out.println("Hash " + i + ": " + hash);
            System.out.println("  ✓ Verifica corretamente: " + verifies);
            
            assertTrue(verifies, "Cada hash deve verificar corretamente");
        }
        
        System.out.println("\n🔑 Benefícios do salt único:");
        System.out.println("  • Mesmo que dois usuários tenham a mesma senha, os hashes são diferentes");
        System.out.println("  • Protege contra ataques de rainbow table");
        System.out.println("  • Cada hash é único, mesmo para a mesma senha");
    }
    
    @Test
    public void testSpecificPasswordExample() {
        System.out.println("\n=== EXEMPLO ESPECÍFICO COM A SENHA SOLICITADA ===");
        
        String password = "Leader@2025!Strong#Pass";
        System.out.println("Senha para teste: " + password);
        
        // Processo de registro
        System.out.println("\n📝 REGISTRO:");
        String hash1 = passwordEncoder.encode(password);
        System.out.println("Hash gerado: " + hash1);
        
        // Processo de login bem-sucedido
        System.out.println("\n🔓 LOGIN CORRETO:");
        boolean correctLogin = passwordEncoder.matches(password, hash1);
        System.out.println("Senha fornecida: " + password);
        System.out.println("Resultado: " + (correctLogin ? "✅ AUTORIZADO" : "❌ NEGADO"));
        
        // Processo de login com senha incorreta
        System.out.println("\n🔒 LOGIN INCORRETO:");
        String wrongPass = "leader@2025!strong#pass"; // lowercase
        boolean incorrectLogin = passwordEncoder.matches(wrongPass, hash1);
        System.out.println("Senha fornecida: " + wrongPass);
        System.out.println("Resultado: " + (incorrectLogin ? "✅ AUTORIZADO" : "❌ NEGADO"));
        
        // Verificações
        assertTrue(correctLogin, "Senha correta deve ser aceita");
        assertFalse(incorrectLogin, "Senha incorreta deve ser rejeitada");
        
        System.out.println("\n🎯 RESULTADO FINAL:");
        System.out.println("✅ Sistema de autenticação funcionando corretamente!");
        System.out.println("✅ Senha sensível a maiúsculas/minúsculas");
        System.out.println("✅ Criptografia BCrypt aplicada com sucesso");
    }
    
    @Test
    public void testCompleteAuthenticationFlow() {
        System.out.println("\n=== FLUXO COMPLETO DE AUTENTICAÇÃO ===");
        
        // Simular base de dados de usuários
        String[][] users = {
            {"admin", "admin123"},
            {"user1", "Leader@2025!Strong#Pass"},
            {"user2", "MySecureP@ssw0rd"},
            {"guest", "Guest123!"}
        };
        
        System.out.println("👥 Criando base de usuários com senhas criptografadas:");
        
        // "Registrar" usuários (criar hashes)
        String[][] userDatabase = new String[users.length][3]; // username, hash, original (só para teste)
        
        for (int i = 0; i < users.length; i++) {
            String username = users[i][0];
            String password = users[i][1];
            String hash = passwordEncoder.encode(password);
            
            userDatabase[i][0] = username;
            userDatabase[i][1] = hash;
            userDatabase[i][2] = password; // em produção, isso NUNCA seria armazenado
            
            System.out.println("  " + username + " -> Hash: " + hash.substring(0, 20) + "...");
        }
        
        System.out.println("\n🔐 Testando logins:");
        
        // Teste de login bem-sucedido
        String loginUser = "user1";
        String loginPassword = "Leader@2025!Strong#Pass";
        
        boolean found = false;
        for (String[] user : userDatabase) {
            if (user[0].equals(loginUser)) {
                boolean loginSuccess = passwordEncoder.matches(loginPassword, user[1]);
                System.out.println("  " + loginUser + " com senha '" + loginPassword + "': " + 
                                 (loginSuccess ? "✅ SUCESSO" : "❌ FALHA"));
                assertTrue(loginSuccess, "Login deve ser bem-sucedido");
                found = true;
                break;
            }
        }
        assertTrue(found, "Usuário deve existir na base");
        
        // Teste de login com senha incorreta
        loginPassword = "senhaerrada";
        for (String[] user : userDatabase) {
            if (user[0].equals(loginUser)) {
                boolean loginFail = passwordEncoder.matches(loginPassword, user[1]);
                System.out.println("  " + loginUser + " com senha '" + loginPassword + "': " + 
                                 (loginFail ? "✅ SUCESSO" : "❌ FALHA"));
                assertFalse(loginFail, "Login deve falhar com senha incorreta");
                break;
            }
        }
        
        System.out.println("\n✅ Fluxo de autenticação testado com sucesso!");
    }
}
