"""Performance tests for dashboard GUI."""

import asyncio
import os
import time
from unittest.mock import patch

import pytest
from fastapi.testclient import TestClient
from playwright.async_api import Error, async_playwright

# Patch settings before importing app
with patch.dict("os.environ", {
    "AI_PROXY_MASTER_KEY": "sk-test-e2e",
    "ANTHROPIC_API_KEY": "sk-ant-test",
    "OPENAI_API_KEY": "sk-test",
    "DEEPSEEK_API_KEY": "sk-ds-test",
    "GOOGLE_AI_KEY": "AI-test",
    "OPENROUTER_API_KEY": "sk-or-test",
    "GROQ_API_KEY": "gsk-test",
    "REDIS_URL": "redis://localhost:6379/0",
}):
    from proxym.main import app

AUTH = {"Authorization": "Bearer sk-test-e2e"}


@pytest.fixture(scope="session")
def event_loop():
    """Create an instance of the default event loop for the test session."""
    loop = asyncio.get_event_loop_policy().new_event_loop()
    yield loop
    loop.close()


@pytest.fixture
async def browser():
    """Launch Playwright browser."""
    async with async_playwright() as p:
        try:
            browser = await p.chromium.launch(headless=True)
        except Error as e:
            pytest.skip(str(e))
        yield browser
        await browser.close()


@pytest.fixture
async def page(browser):
    """Create a new page."""
    page = await browser.new_page()
    yield page
    await page.close()


@pytest.fixture
def test_client():
    """FastAPI test client."""
    return TestClient(app)


@pytest.fixture
async def server(test_client):
    """Start the test server."""
    import threading
    import uvicorn
    import socket
    import time
    
    # Find a free port
    sock = socket.socket()
    sock.bind(("", 0))
    port = sock.getsockname()[1]
    sock.close()
    
    server_url = f"http://localhost:{port}"
    
    def run_server():
        uvicorn.run(app, host="localhost", port=port, log_level="error")
    
    thread = threading.Thread(target=run_server, daemon=True)
    thread.start()
    
    # Wait for server to be ready
    time.sleep(2)
    
    yield server_url


class TestDashboardPerformance:
    """Performance tests for dashboard functionality."""

    async def test_page_load_performance(self, page, server):
        """Test dashboard page load speed."""
        dashboard_html = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <title>Performance Test Dashboard</title>
            <script src="https://cdn.tailwindcss.com"></script>
        </head>
        <body>
            <div class="min-h-screen bg-gray-50">
                <header class="bg-white border-b border-gray-200 px-6 py-3">
                    <h1 class="text-lg font-semibold text-gray-900">Performance Test</h1>
                </header>
                <main class="max-w-7xl mx-auto px-6 py-6">
                    <div id="content">Loading...</div>
                </main>
            </div>
            <script>
                // Simulate content loading
                setTimeout(() => {{
                    document.getElementById('content').innerHTML = 
                        '<div class="text-center py-8">Dashboard loaded</div>';
                }}, 100);
            </script>
        </body>
        </html>
        """
        
        await page.route("**/*", lambda route: route.fulfill(
            status=200,
            body=dashboard_html,
            headers={"Content-Type": "text/html"}
        ))
        
        # Measure page load time
        start_time = time.time()
        await page.goto(server)
        await page.wait_for_load_state("networkidle")
        load_time = time.time() - start_time
        
        # Page should load within 3 seconds
        assert load_time < 3.0, f"Page load took {load_time:.2f}s, expected < 3.0s"
        
        # Check content is loaded
        content_text = await page.locator("#content").inner_text()
        assert "Dashboard loaded" in content_text

    async def test_multiple_tab_switching_performance(self, page, server):
        """Test performance of rapid tab switching."""
        dashboard_html = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <title>Tab Performance Test</title>
            <script src="https://cdn.tailwindcss.com"></script>
        </head>
        <body>
            <div class="min-h-screen bg-gray-50">
                <nav class="bg-white border-b border-gray-200 px-6">
                    <button id="tab1" class="px-4 py-2.5 text-sm font-medium border-b-2 border-blue-600 text-blue-600">Tab 1</button>
                    <button id="tab2" class="px-4 py-2.5 text-sm font-medium border-b-2 border-transparent text-gray-500">Tab 2</button>
                    <button id="tab3" class="px-4 py-2.5 text-sm font-medium border-b-2 border-transparent text-gray-500">Tab 3</button>
                </nav>
                <main class="max-w-7xl mx-auto px-6 py-6">
                    <div id="content">Content for Tab 1</div>
                </main>
            </div>
            <script>
                const tabs = ['tab1', 'tab2', 'tab3'];
                const contents = [
                    'Content for Tab 1',
                    'Content for Tab 2', 
                    'Content for Tab 3'
                ];
                
                tabs.forEach((tabId, index) => {{
                    document.getElementById(tabId).addEventListener('click', () => {{
                        // Update tab styles
                        tabs.forEach(t => {{
                            const btn = document.getElementById(t);
                            btn.className = t === tabId 
                                ? 'px-4 py-2.5 text-sm font-medium border-b-2 border-blue-600 text-blue-600'
                                : 'px-4 py-2.5 text-sm font-medium border-b-2 border-transparent text-gray-500';
                        }});
                        // Update content
                        document.getElementById('content').textContent = contents[index];
                    }});
                }});
            </script>
        </body>
        </html>
        """
        
        await page.route("**/*", lambda route: route.fulfill(
            status=200,
            body=dashboard_html,
            headers={"Content-Type": "text/html"}
        ))
        
        await page.goto(server)
        await page.wait_for_load_state("networkidle")
        
        # Test rapid tab switching
        start_time = time.time()
        
        for i in range(10):  # Switch tabs 10 times
            await page.click("#tab2")
            await page.wait_for_timeout(50)  # Small delay to simulate user interaction
            await page.click("#tab3")
            await page.wait_for_timeout(50)
            await page.click("#tab1")
            await page.wait_for_timeout(50)
        
        total_time = time.time() - start_time
        
        # Tab switching should be responsive (less than 3 seconds for 30 switches)
        assert total_time < 3.0, f"Tab switching took {total_time:.2f}s, expected < 3.0s"
        
        # Verify final state
        content_text = await page.locator("#content").inner_text()
        assert "Content for Tab 1" in content_text

    async def test_form_submission_performance(self, page, server):
        """Test performance of form submission."""
        dashboard_html = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <title>Form Performance Test</title>
            <script src="https://cdn.tailwindcss.com"></script>
        </head>
        <body>
            <div class="min-h-screen bg-gray-50 p-6">
                <div class="bg-white rounded-lg shadow p-4">
                    <h2 class="text-lg font-semibold mb-4">Performance Test Form</h2>
                    <form id="perf-form">
                        <input id="field1" class="border p-2 mb-2 w-full" placeholder="Field 1">
                        <input id="field2" class="border p-2 mb-2 w-full" placeholder="Field 2">
                        <input id="field3" class="border p-2 mb-2 w-full" placeholder="Field 3">
                        <button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded">Submit</button>
                    </form>
                    <div id="result" class="mt-4"></div>
                </div>
            </div>
            <script>
                document.getElementById('perf-form').addEventListener('submit', (e) => {{
                    e.preventDefault();
                    
                    // Simulate form processing
                    setTimeout(() => {{
                        const field1 = document.getElementById('field1').value;
                        const field2 = document.getElementById('field2').value;
                        const field3 = document.getElementById('field3').value;
                        
                        document.getElementById('result').innerHTML = 
                            '<span class="text-green-600">Form submitted successfully</span>';
                    }}, 50); // Simulate 50ms processing time
                }});
            </script>
        </body>
        </html>
        """
        
        await page.route("**/*", lambda route: route.fulfill(
            status=200,
            body=dashboard_html,
            headers={"Content-Type": "text/html"}
        ))
        
        await page.goto(server)
        await page.wait_for_load_state("networkidle")
        
        # Test form filling and submission
        start_time = time.time()
        
        # Fill form quickly
        await page.fill("#field1", "Test Value 1")
        await page.fill("#field2", "Test Value 2")
        await page.fill("#field3", "Test Value 3")
        
        # Submit form
        await page.click("button[type='submit']")
        
        # Wait for result
        await page.wait_for_selector("#result", state="visible")
        await page.wait_for_timeout(100)  # Wait for form processing
        
        total_time = time.time() - start_time
        
        # Form submission should be fast (less than 1 second)
        assert total_time < 1.0, f"Form submission took {total_time:.2f}s, expected < 1.0s"
        
        # Verify result
        result_text = await page.locator("#result").inner_text()
        assert "Form submitted successfully" in result_text

    async def test_large_content_rendering(self, page, server):
        """Test performance of rendering large content."""
        # Generate large content
        large_content = "<div class='space-y-2'>"
        for i in range(100):  # 100 items
            large_content += f"""
            <div class='bg-white rounded-lg shadow p-4'>
                <h3 class='font-semibold'>Item {i+1}</h3>
                <p class='text-gray-600'>This is the content for item {i+1}. 
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
                Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
                <div class='mt-2 flex gap-2'>
                    <span class='px-2 py-1 bg-blue-100 text-blue-700 rounded text-xs'>Tag {i+1}</span>
                    <span class='px-2 py-1 bg-green-100 text-green-700 rounded text-xs'>Active</span>
                </div>
            </div>
            """
        large_content += "</div>"
        
        dashboard_html = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <title>Large Content Performance Test</title>
            <script src="https://cdn.tailwindcss.com"></script>
        </head>
        <body>
            <div class="min-h-screen bg-gray-50 p-6">
                <h1 class="text-2xl font-bold mb-6">Large Content Test</h1>
                <button id="load-btn" class="bg-blue-500 text-white px-4 py-2 rounded mb-4">Load Large Content</button>
                <div id="content-container"></div>
            </div>
            <script>
                document.getElementById('load-btn').addEventListener('click', () => {{
                    const content = `{large_content}`;
                    document.getElementById('content-container').innerHTML = content;
                }});
            </script>
        </body>
        </html>
        """
        
        await page.route("**/*", lambda route: route.fulfill(
            status=200,
            body=dashboard_html,
            headers={"Content-Type": "text/html"}
        ))
        
        await page.goto(server)
        await page.wait_for_load_state("networkidle")
        
        # Test large content rendering
        start_time = time.time()
        
        await page.click("#load-btn")
        
        # Wait for content to render
        await page.wait_for_selector("#content-container div", state="visible")
        await page.wait_for_timeout(1000)  # Allow more time for rendering
        
        total_time = time.time() - start_time
        
        # Large content should render within 3 seconds
        assert total_time < 3.0, f"Large content rendering took {total_time:.2f}s, expected < 3.0s"
        
        # Verify content was rendered - check for any divs in container
        container_content = await page.locator("#content-container").inner_text()
        assert "Item 1" in container_content, "Large content not rendered properly"
        
        # Count items by looking for specific text patterns
        items_found = 0
        for i in range(1, 101):
            if f"Item {i}" in container_content:
                items_found += 1
        
        assert items_found >= 50, f"Expected at least 50 items, got {items_found}"

    async def test_memory_usage_simulation(self, page, server):
        """Test that dashboard doesn't cause obvious memory leaks."""
        dashboard_html = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <title>Memory Test</title>
            <script src="https://cdn.tailwindcss.com"></script>
        </head>
        <body>
            <div class="min-h-screen bg-gray-50 p-6">
                <h1 class="text-2xl font-bold mb-6">Memory Usage Test</h1>
                <button id="create-btn" class="bg-blue-500 text-white px-4 py-2 rounded mb-4">Create Elements</button>
                <button id="clear-btn" class="bg-red-500 text-white px-4 py-2 rounded mb-4">Clear Elements</button>
                <div id="container"></div>
            </div>
            <script>
                let elements = [];
                
                document.getElementById('create-btn').addEventListener('click', () => {{
                    for (let i = 0; i < 50; i++) {{
                        const div = document.createElement('div');
                        div.className = 'bg-white rounded-lg shadow p-4 mb-2';
                        div.innerHTML = `
                            <h3 class='font-semibold'>Element ${{elements.length + i + 1}}</h3>
                            <p class='text-gray-600'>Content ${{elements.length + i + 1}}</p>
                        `;
                        document.getElementById('container').appendChild(div);
                        elements.push(div);
                    }}
                }});
                
                document.getElementById('clear-btn').addEventListener('click', () => {{
                    document.getElementById('container').innerHTML = '';
                    elements = [];
                }});
            </script>
        </body>
        </html>
        """
        
        await page.route("**/*", lambda route: route.fulfill(
            status=200,
            body=dashboard_html,
            headers={"Content-Type": "text/html"}
        ))
        
        await page.goto(server)
        await page.wait_for_load_state("networkidle")
        
        # Test multiple create/clear cycles
        for cycle in range(5):
            # Create elements
            await page.click("#create-btn")
            await page.wait_for_timeout(100)
            
            # Verify elements were created
            elements_count = await page.locator("#container > div").count()
            assert elements_count > 0, f"Cycle {cycle + 1}: No elements created"
            
            # Clear elements
            await page.click("#clear-btn")
            await page.wait_for_timeout(100)
            
            # Verify elements were cleared
            elements_count = await page.locator("#container > div").count()
            assert elements_count == 0, f"Cycle {cycle + 1}: Elements not cleared"
        
        # Final check - page should still be responsive
        await page.click("#create-btn")
        await page.wait_for_timeout(100)
        elements_count = await page.locator("#container > div").count()
        assert elements_count > 0, "Final check: Could not create elements"
