import pytest
import requests
import time
import pyotp
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options

class TestIntegrationMenu:
    """Testes de integração para navegação pelos menus como um usuário real"""
    
    @pytest.fixture(scope="class")
    def driver(self):
        """Configurar driver do Selenium"""
        chrome_options = Options()
        chrome_options.add_argument("--headless")  # Executar sem interface gráfica
        chrome_options.add_argument("--no-sandbox")
        chrome_options.add_argument("--disable-dev-shm-usage")
        
        driver = webdriver.Chrome(options=chrome_options)
        driver.implicitly_wait(10)
        yield driver
        driver.quit()
    
    def test_complete_menu_navigation(self, driver):
        """Testa navegação completa pelos menus usando Selenium"""
        base_url = "http://localhost:5000"
        
        # 1. Acessar página de login
        driver.get(f"{base_url}/login")
        assert "Login" in driver.title
        
        # 2. Fazer login
        driver.find_element(By.NAME, "email").send_keys("admin")
        driver.find_element(By.NAME, "password").send_keys("admin123")
        
        # Gerar OTP
        totp = pyotp.TOTP('JBSWY3DPEHPK3PXP')
        current_otp = totp.now()
        driver.find_element(By.NAME, "otp").send_keys(current_otp)
        
        driver.find_element(By.XPATH, "//button[@type='submit']").click()
        
        # 3. Verificar se chegou na home
        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CLASS_NAME, "navbar"))
        )
        
        # 4. Testar cada menu
        menus_to_test = [
            ("Militantes", "/militantes"),
            ("Financeiro", "/cotas"),
            ("Materiais", "/materiais"),
        ]
        
        for menu_name, expected_url in menus_to_test:
            # Encontrar e clicar no menu
            menu_link = WebDriverWait(driver, 10).until(
                EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, menu_name))
            )
            menu_link.click()
            
            # Aguardar dropdown aparecer e clicar no primeiro item
            time.sleep(1)
            dropdown_items = driver.find_elements(By.CLASS_NAME, "dropdown-item")
            if dropdown_items:
                dropdown_items[0].click()
                
                # Verificar se a página carregou corretamente
                WebDriverWait(driver, 10).until(
                    lambda d: expected_url in d.current_url or d.find_elements(By.CLASS_NAME, "container")
                )
                
                # Verificar se não há erros na página
                assert "Erro ao carregar dados do usuário" not in driver.page_source
                assert "500" not in driver.page_source
                assert "404" not in driver.page_source
    
    def test_api_menu_navigation(self):
        """Testa navegação pelos menus usando requests (simulando browser)"""
        base_url = "http://localhost:5000"
        session = requests.Session()
        
        # 1. Fazer login via API
        totp = pyotp.TOTP('JBSWY3DPEHPK3PXP')
        current_otp = totp.now()
        
        login_response = session.post(f"{base_url}/api/login", 
                                    json={
                                        'email': 'admin',
                                        'password': 'admin123',
                                        'otp': current_otp
                                    },
                                    headers={'Content-Type': 'application/json'})
        
        assert login_response.status_code == 200
        
        # 2. Testar todas as rotas do menu
        menu_routes = [
            "/",
            "/dashboard", 
            "/militantes",
            "/militantes/novo",
            "/cotas",
            "/cotas/nova",
            "/pagamentos",
            "/pagamentos/novo",
            "/materiais",
            "/materiais/novo",
            "/tipos-materiais",
            "/tipos-materiais/novo",
            "/admin/dashboard"
        ]
        
        failed_routes = []
        
        for route in menu_routes:
            try:
                response = session.get(f"{base_url}{route}")
                if response.status_code != 200:
                    failed_routes.append((route, response.status_code))
                elif "Erro ao carregar dados do usuário" in response.text:
                    failed_routes.append((route, "Permission Error"))
                elif "csrf_token" in response.text and "is undefined" in response.text:
                    failed_routes.append((route, "CSRF Error"))
            except Exception as e:
                failed_routes.append((route, str(e)))
        
        # 3. Verificar resultados
        if failed_routes:
            error_msg = "Rotas com falhas:\n"
            for route, error in failed_routes:
                error_msg += f"  {route}: {error}\n"
            pytest.fail(error_msg)
    
    def test_menu_responsiveness(self):
        """Testa se os menus respondem corretamente em diferentes cenários"""
        base_url = "http://localhost:5000"
        
        # Testar sem autenticação
        response = requests.get(f"{base_url}/militantes")
        assert response.status_code in [302, 401], "Rota protegida deveria redirecionar"
        
        # Testar com autenticação
        session = requests.Session()
        totp = pyotp.TOTP('JBSWY3DPEHPK3PXP')
        current_otp = totp.now()
        
        login_response = session.post(f"{base_url}/api/login", 
                                    json={
                                        'email': 'admin',
                                        'password': 'admin123',
                                        'otp': current_otp
                                    },
                                    headers={'Content-Type': 'application/json'})
        
        assert login_response.status_code == 200
        
        # Testar acesso às rotas protegidas
        protected_routes = ["/militantes", "/cotas", "/pagamentos", "/materiais"]
        
        for route in protected_routes:
            response = session.get(f"{base_url}{route}")
            assert response.status_code == 200, f"Rota {route} falhou após autenticação"
            
            # Verificar se não há erros específicos
            assert "Erro ao carregar dados do usuário" not in response.text
            assert "csrf_token() is undefined" not in response.text
    
    def test_menu_performance(self):
        """Testa performance dos menus"""
        base_url = "http://localhost:5000"
        session = requests.Session()
        
        # Login
        totp = pyotp.TOTP('JBSWY3DPEHPK3PXP')
        current_otp = totp.now()
        
        session.post(f"{base_url}/api/login", 
                    json={
                        'email': 'admin',
                        'password': 'admin123',
                        'otp': current_otp
                    },
                    headers={'Content-Type': 'application/json'})
        
        # Testar tempo de resposta dos menus
        routes_to_test = ["/", "/militantes", "/cotas", "/pagamentos", "/materiais"]
        slow_routes = []
        
        for route in routes_to_test:
            start_time = time.time()
            response = session.get(f"{base_url}{route}")
            end_time = time.time()
            
            response_time = end_time - start_time
            
            if response_time > 5.0:  # Mais de 5 segundos é muito lento
                slow_routes.append((route, response_time))
        
        if slow_routes:
            error_msg = "Rotas com performance ruim:\n"
            for route, time_taken in slow_routes:
                error_msg += f"  {route}: {time_taken:.2f}s\n"
            pytest.fail(error_msg) 