import pytest
from flask import url_for
from flask_login import login_user
from functions.database import get_db_connection, Usuario
import pyotp

class TestMenuNavigation:
    """Testes para verificar se todos os menus estão funcionando corretamente"""
    
    @pytest.fixture
    def authenticated_client(self, client, app):
        """Cliente autenticado para testes"""
        with app.test_request_context():
            # Fazer login via API
            totp = pyotp.TOTP('JBSWY3DPEHPK3PXP')
            current_otp = totp.now()
            
            response = client.post('/api/login', 
                                 json={
                                     'email': 'admin',
                                     'password': 'admin123',
                                     'otp': current_otp
                                 },
                                 headers={'Content-Type': 'application/json'})
            
            assert response.status_code == 200
            return client
    
    def test_home_menu(self, authenticated_client):
        """Testa se o menu Home está funcionando"""
        response = authenticated_client.get('/')
        assert response.status_code == 200
        
        response = authenticated_client.get('/dashboard')
        assert response.status_code == 200
    
    def test_militantes_menu(self, authenticated_client):
        """Testa se o menu Militantes está funcionando"""
        response = authenticated_client.get('/militantes')
        assert response.status_code == 200
        
        # Testar outras rotas do menu militantes
        response = authenticated_client.get('/militantes/novo')
        assert response.status_code == 200
    
    def test_financeiro_menu(self, authenticated_client):
        """Testa se o menu Financeiro está funcionando"""
        # Testar Cotas
        response = authenticated_client.get('/cotas')
        assert response.status_code == 200
        
        # Testar Pagamentos
        response = authenticated_client.get('/pagamentos')
        assert response.status_code == 200
    
    def test_materiais_menu(self, authenticated_client):
        """Testa se o menu Materiais está funcionando"""
        # Testar Listar Materiais
        response = authenticated_client.get('/materiais')
        assert response.status_code == 200
        
        # Testar Tipos de Materiais
        response = authenticated_client.get('/tipos-materiais')
        assert response.status_code == 200
        
        # Testar formulário de novo material
        response = authenticated_client.get('/materiais/novo')
        assert response.status_code == 200
        
        # Testar formulário de novo tipo
        response = authenticated_client.get('/tipos-materiais/novo')
        assert response.status_code == 200
    
    def test_admin_menu(self, authenticated_client):
        """Testa se o menu Admin está funcionando"""
        response = authenticated_client.get('/admin/dashboard')
        assert response.status_code == 200
    
    def test_user_menu(self, authenticated_client):
        """Testa se o menu do usuário está funcionando"""
        # Testar logout
        response = authenticated_client.get('/logout')
        assert response.status_code in [200, 302]  # Pode redirecionar
    
    def test_all_menu_links_in_template(self, authenticated_client):
        """Testa se todos os links do menu no template base estão funcionando"""
        # Primeiro, obter a página inicial para verificar os links
        response = authenticated_client.get('/')
        assert response.status_code == 200
        
        # Lista de URLs que devem estar funcionando
        menu_urls = [
            '/militantes',
            '/cotas', 
            '/pagamentos',
            '/materiais',
            '/tipos-materiais',
            '/dashboard',
            '/admin/dashboard'
        ]
        
        for url in menu_urls:
            response = authenticated_client.get(url)
            assert response.status_code == 200, f"URL {url} falhou com status {response.status_code}"
    
    def test_menu_permissions(self, authenticated_client):
        """Testa se as permissões dos menus estão funcionando"""
        # Testar acesso a páginas que requerem login
        response = authenticated_client.get('/militantes')
        assert response.status_code == 200
        
        response = authenticated_client.get('/cotas')
        assert response.status_code == 200
        
        response = authenticated_client.get('/pagamentos')
        assert response.status_code == 200
        
        response = authenticated_client.get('/materiais')
        assert response.status_code == 200
    
    def test_menu_without_authentication(self, client):
        """Testa se os menus redirecionam corretamente quando não autenticado"""
        # Páginas que requerem login devem redirecionar
        protected_urls = [
            '/militantes',
            '/cotas',
            '/pagamentos', 
            '/materiais',
            '/dashboard',
            '/admin/dashboard'
        ]
        
        for url in protected_urls:
            response = client.get(url, follow_redirects=False)
            assert response.status_code in [302, 401], f"URL {url} deveria redirecionar ou retornar 401"
    
    def test_api_endpoints(self, authenticated_client):
        """Testa se os endpoints da API estão funcionando"""
        response = authenticated_client.get('/api/status')
        assert response.status_code == 200
        
        # Verificar se retorna JSON válido
        data = response.get_json()
        assert data is not None
        assert 'authenticated' in data
        assert data['authenticated'] is True
    
    def test_error_handling_menu(self, authenticated_client):
        """Testa se páginas inexistentes retornam erro apropriado"""
        response = authenticated_client.get('/pagina-inexistente')
        assert response.status_code == 404
        
        response = authenticated_client.get('/militantes/999999')
        assert response.status_code in [404, 500]  # Pode ser 404 ou erro de servidor 