package com.social.media;

import com.social.media.dto.UserDto;
import com.social.media.dto.UserCredentialsDto;
import com.social.media.service.UserService;
import com.social.media.service.UserCredentialsService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

/**
 * Teste para investigar problemas de autenticação
 */
@SpringBootTest
@Transactional
public class AuthenticationDebuggingTest {
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private UserCredentialsService userCredentialsService;
    
    @Test
    public void debugAuthenticationIssues() {
        System.out.println("=== DEBUGGING DE PROBLEMAS DE AUTENTICAÇÃO ===");
        
        // Vamos procurar usuários que possam ter essa senha
        String expectedPassword = "Leader@2025!Strong#Pass";
        String expectedHash = "$2a$10$CQVd5R6UaFV2xRSIt3BhJO2KklkaWGKCYDhR1D1S/jl3xtsWyMYSu";
        
        System.out.println("Procurando usuário com o hash específico...");
        
        // Como não temos acesso direto ao repositório de credenciais via hash,
        // vamos tentar algumas abordagens diferentes
        
        // 1. Verificar se há algum usuário com email comum
        checkUserByEmail("admin@example.com");
        checkUserByEmail("admin@admin.com");
        checkUserByEmail("user@example.com");
        checkUserByEmail("test@test.com");
        checkUserByEmail("demo@demo.com");
        
        // 2. Verificar os primeiros usuários do sistema
        System.out.println("\n=== VERIFICANDO USUÁRIOS NO SISTEMA ===");
        try {
            // Vamos tentar buscar usuários por ID
            for (Long userId = 1L; userId <= 10L; userId++) {
                checkUserById(userId, expectedPassword, expectedHash);
            }
        } catch (Exception e) {
            System.out.println("Erro ao buscar usuários: " + e.getMessage());
        }
    }
    
    private void checkUserByEmail(String email) {
        try {
            Optional<UserDto> userOpt = userService.findByEmail(email);
            if (userOpt.isPresent()) {
                UserDto user = userOpt.get();
                System.out.println("\n✅ Usuário encontrado:");
                System.out.println("  ID: " + user.getId());
                System.out.println("  Email: " + user.getEmail());
                System.out.println("  Nome: " + user.getName());
                System.out.println("  Status: " + user.getStatus());
                System.out.println("  Ativo: " + !Boolean.TRUE.equals(user.getDeleted()));
                
                // Verificar credenciais
                checkUserCredentials(user.getId());
            } else {
                System.out.println("❌ Usuário não encontrado: " + email);
            }
        } catch (Exception e) {
            System.out.println("❌ Erro ao buscar usuário " + email + ": " + e.getMessage());
        }
    }
    
    private void checkUserById(Long userId, String expectedPassword, String expectedHash) {
        try {
            // Verificar se o usuário existe
            UserDto user = userService.getUserById(userId);
            if (user != null) {
                
                // Verificar credenciais
                Optional<UserCredentialsDto> credentialsOpt = userCredentialsService.findByUserId(userId);
                if (credentialsOpt.isPresent()) {
                    UserCredentialsDto credentials = credentialsOpt.get();
                    
                    // Testar autenticação
                    boolean authResult = userCredentialsService.authenticate(userId, expectedPassword);
                    
                    if (authResult) {
                        System.out.println("\n🎉 USUÁRIO COM A SENHA ENCONTRADO!");
                        System.out.println("  ID: " + user.getId());
                        System.out.println("  Email: " + user.getEmail());
                        System.out.println("  Nome: " + user.getName());
                        System.out.println("  Status: " + user.getStatus());
                        System.out.println("  Ativo: " + !Boolean.TRUE.equals(user.getDeleted()));
                        
                        printUserCredentialsInfo(credentials);
                        
                        // Verificar se há problemas que impedem o login
                        checkLoginBlockers(user, credentials);
                    }
                }
            }
        } catch (Exception e) {
            // Usuário não existe ou erro - ignorar silenciosamente
        }
    }
    
    private void checkUserCredentials(Long userId) {
        try {
            Optional<UserCredentialsDto> credentialsOpt = userCredentialsService.findByUserId(userId);
            if (credentialsOpt.isPresent()) {
                UserCredentialsDto credentials = credentialsOpt.get();
                printUserCredentialsInfo(credentials);
            } else {
                System.out.println("  ❌ Credenciais não encontradas");
            }
        } catch (Exception e) {
            System.out.println("  ❌ Erro ao buscar credenciais: " + e.getMessage());
        }
    }
    
    private void printUserCredentialsInfo(UserCredentialsDto credentials) {
        System.out.println("  --- Credenciais ---");
        System.out.println("  Conta bloqueada: " + credentials.getIsAccountLocked());
        System.out.println("  Bloqueio permanente: " + credentials.getIsPermanentlyLocked());
        System.out.println("  Tentativas falhadas: " + credentials.getFailedLoginAttempts());
        System.out.println("  Máximo tentativas: " + credentials.getMaxFailedAttempts());
        System.out.println("  2FA habilitado: " + credentials.getTwoFactorEnabled());
        System.out.println("  Último login: " + credentials.getLastLoginAt());
        System.out.println("  Senha alterada em: " + credentials.getPasswordChangedAt());
        
        if (credentials.getRemainingLockoutMinutes() != null && credentials.getRemainingLockoutMinutes() > 0) {
            System.out.println("  ⚠️ Tempo restante de bloqueio: " + credentials.getRemainingLockoutMinutes() + " minutos");
        }
    }
    
    private void checkLoginBlockers(UserDto user, UserCredentialsDto credentials) {
        System.out.println("\n=== VERIFICANDO POSSÍVEIS BLOQUEADORES DE LOGIN ===");
        
        boolean hasBlockers = false;
        
        // 1. Usuário deletado
        if (Boolean.TRUE.equals(user.getDeleted())) {
            System.out.println("❌ BLOQUEADOR: Usuário está marcado como deletado");
            hasBlockers = true;
        }
        
        // 2. Status do usuário
        if (!"ACTIVE".equals(user.getStatus())) {
            System.out.println("❌ BLOQUEADOR: Status do usuário não é ACTIVE: " + user.getStatus());
            hasBlockers = true;
        }
        
        // 3. Conta bloqueada
        if (Boolean.TRUE.equals(credentials.getIsAccountLocked())) {
            System.out.println("❌ BLOQUEADOR: Conta está bloqueada");
            hasBlockers = true;
        }
        
        // 4. Bloqueio permanente
        if (Boolean.TRUE.equals(credentials.getIsPermanentlyLocked())) {
            System.out.println("❌ BLOQUEADOR: Conta está permanentemente bloqueada");
            hasBlockers = true;
        }
        
        // 5. Muitas tentativas falhadas
        if (credentials.getFailedLoginAttempts() != null && 
            credentials.getMaxFailedAttempts() != null &&
            credentials.getFailedLoginAttempts() >= credentials.getMaxFailedAttempts()) {
            System.out.println("❌ BLOQUEADOR: Muitas tentativas falhadas (" + 
                             credentials.getFailedLoginAttempts() + "/" + credentials.getMaxFailedAttempts() + ")");
            hasBlockers = true;
        }
        
        // 6. Tempo de bloqueio restante
        if (credentials.getRemainingLockoutMinutes() != null && credentials.getRemainingLockoutMinutes() > 0) {
            System.out.println("❌ BLOQUEADOR: Conta bloqueada por mais " + 
                             credentials.getRemainingLockoutMinutes() + " minutos");
            hasBlockers = true;
        }
        
        if (!hasBlockers) {
            System.out.println("✅ Nenhum bloqueador encontrado! A conta deveria permitir login.");
            
            // Vamos testar a autenticação diretamente
            System.out.println("\n=== TESTE DIRETO DE AUTENTICAÇÃO ===");
            boolean authResult = userCredentialsService.authenticate(user.getId(), "Leader@2025!Strong#Pass");
            System.out.println("Resultado da autenticação: " + authResult);
            
            if (!authResult) {
                System.out.println("❌ Autenticação falhou mesmo sem bloqueadores visíveis!");
                System.out.println("💡 Isso pode indicar um problema na implementação da autenticação");
            } else {
                System.out.println("✅ Autenticação bem-sucedida!");
                System.out.println("💡 O problema pode estar na interface de login ou no fluxo de autenticação");
            }
        } else {
            System.out.println("\n💡 SOLUÇÃO: Remova os bloqueadores encontrados para permitir o login");
            
            // Sugerir comandos para desbloqueio
            System.out.println("\n=== COMANDOS PARA DESBLOQUEIO ===");
            if (Boolean.TRUE.equals(credentials.getIsAccountLocked()) || 
                Boolean.TRUE.equals(credentials.getIsPermanentlyLocked())) {
                System.out.println("Para desbloquear a conta:");
                System.out.println("userCredentialsService.unlockAccount(" + user.getId() + "L);");
            }
            
            if (credentials.getFailedLoginAttempts() != null && credentials.getFailedLoginAttempts() > 0) {
                System.out.println("Para resetar tentativas falhadas:");
                System.out.println("userCredentialsService.resetFailedAttempts(" + user.getId() + "L);");
            }
        }
    }
}
