#!/usr/bin/env python3
"""Test MaxCpp Phase 33: C++ Tree Navigation Bulk Operations."""

import time
from cutysoup import CutySoup
from bs4 import BeautifulSoup

# Test HTML with complex navigation structure
test_html = """
<html>
<head>
    <title>Navigation Test</title>
</head>
<body>
    <header id="header">
        <nav class="main-nav">
            <ul class="nav-list">
                <li class="nav-item">Home</li>
                <li class="nav-item">About</li>
                <li class="nav-item">Services</li>
                <li class="nav-item">Contact</li>
            </ul>
        </nav>
    </header>
    
    <main class="content">
        <section class="hero">
            <h1>Hero Title</h1>
            <p>Hero paragraph with content.</p>
        </section>
        
        <section class="features">
            <div class="feature">
                <h2>Feature 1</h2>
                <p>Feature 1 description</p>
                <span>Feature 1 details</span>
            </div>
            <div class="feature">
                <h2>Feature 2</h2>
                <p>Feature 2 description</p>
                <span>Feature 2 details</span>
            </div>
            <div class="feature">
                <h2>Feature 3</h2>
                <p>Feature 3 description</p>
                <span>Feature 3 details</span>
            </div>
        </section>
    </main>
    
    <footer id="footer">
        <p>Footer content</p>
    </footer>
</body>
</html>
"""

def test_cpp_navigation_methods():
    """Test the new C++ navigation bulk operations."""
    print("MaxCpp Phase 33: C++ Tree Navigation Tests")
    print("=" * 50)
    
    soup = CutySoup(test_html)
    
    # Test direct access to C++ methods
    main_section = soup.find('main', class_='content')
    first_feature = soup.find('div', class_='feature')
    nav_item = soup.find('li', class_='nav-item')
    
    print("🔍 Testing Direct C++ Navigation Methods:")
    
    # Test get_all_descendants
    print("\n1. get_all_descendants() (C++ bulk):")
    descendants = main_section._node.get_all_descendants()
    print(f"   Main descendants: {len(descendants)}")
    print(f"   First 3 tags: {[d.get_name() for d in descendants[:3]]}")
    
    # Test get_all_next_siblings
    print("\n2. get_all_next_siblings() (C++ bulk):")
    next_siblings = first_feature._node.get_all_next_siblings()
    print(f"   Next siblings: {len(next_siblings)}")
    print(f"   Sibling tags: {[s.get_name() for s in next_siblings]}")
    
    # Test get_all_previous_siblings
    last_feature = soup.find_all('div', class_='feature')[-1]
    print("\n3. get_all_previous_siblings() (C++ bulk):")
    prev_siblings = last_feature._node.get_all_previous_siblings()
    print(f"   Previous siblings: {len(prev_siblings)}")
    print(f"   Sibling tags: {[s.get_name() for s in prev_siblings]}")
    
    # Test get_all_parents
    print("\n4. get_all_parents() (C++ bulk):")
    parents = nav_item._node.get_all_parents()
    print(f"   Parent chain: {len(parents)}")
    print(f"   Parent tags: {[p.get_name() for p in parents]}")

def test_python_api_navigation():
    """Test that Python navigation API correctly uses C++ methods."""
    print("\n🔍 Testing Python Navigation API Integration:")
    
    soup = CutySoup(test_html)
    main_section = soup.find('main', class_='content')
    first_feature = soup.find('div', class_='feature')
    nav_item = soup.find('li', class_='nav-item')
    
    # Test descendants property (now uses C++ bulk)
    print("\n1. descendants property (C++ bulk):")
    descendants_list = list(main_section.descendants)
    print(f"   Total descendants: {len(descendants_list)}")
    print(f"   First 3: {[d.name for d in descendants_list[:3]]}")
    
    # Test next_siblings property (now uses C++ bulk)
    print("\n2. next_siblings property (C++ bulk):")
    next_siblings_list = list(first_feature.next_siblings)
    print(f"   Next siblings: {len(next_siblings_list)}")
    print(f"   Types: {[type(s).__name__ for s in next_siblings_list]}")
    
    # Test previous_siblings property (now uses C++ bulk)
    last_li = soup.find_all('li', class_='nav-item')[-1]
    print("\n3. previous_siblings property (C++ bulk):")
    prev_siblings_list = list(last_li.previous_siblings)
    print(f"   Previous siblings: {len(prev_siblings_list)}")
    print(f"   Content: {[str(s).strip()[:20] for s in prev_siblings_list if str(s).strip()]}")
    
    # Test parents property (now uses C++ bulk)
    print("\n4. parents property (C++ bulk):")
    parents_list = list(nav_item.parents)
    print(f"   Parent chain: {len(parents_list)}")
    print(f"   Parent tags: {[p.name for p in parents_list]}")

def benchmark_navigation_performance():
    """Benchmark C++ bulk navigation vs BeautifulSoup4 generators."""
    print("\n🚀 Performance Benchmark: C++ Bulk vs BeautifulSoup4 Generators")
    print("=" * 60)
    
    # Create larger document
    large_html = "<html><body>"
    for i in range(50):
        large_html += f"""
        <section class="section-{i}">
            <div class="container-{i}">
                <h2>Title {i}</h2>
                <p>Paragraph {i}</p>
                <div class="nested-{i}">
                    <span>Span {i}</span>
                    <a href="/link{i}">Link {i}</a>
                </div>
            </div>
        </section>
        """
    large_html += "</body></html>"
    
    print(f"Document size: ~{len(large_html)} characters")
    
    cs_soup = CutySoup(large_html)
    bs_soup = BeautifulSoup(large_html, 'html.parser')
    
    iterations = 100
    
    # Test 1: Descendants navigation
    print("\n1. Descendants Navigation:")
    body_cs = cs_soup.find('body')
    body_bs = bs_soup.find('body')
    
    start_time = time.perf_counter()
    for _ in range(iterations):
        cs_descendants = list(body_cs.descendants)
    cs_time = time.perf_counter() - start_time
    
    start_time = time.perf_counter()
    for _ in range(iterations):
        bs_descendants = list(body_bs.descendants)
    bs_time = time.perf_counter() - start_time
    
    print(f"   CutySoup (C++ bulk): {cs_time:.4f}s ({len(cs_descendants)} descendants)")
    print(f"   BeautifulSoup4 (generator): {bs_time:.4f}s ({len(bs_descendants)} descendants)")
    if cs_time > 0:
        print(f"   Speedup: {bs_time/cs_time:.1f}x")
    
    # Test 2: Parent chain navigation
    print("\n2. Parent Chain Navigation:")
    deep_cs = cs_soup.find('span')
    deep_bs = bs_soup.find('span')
    
    start_time = time.perf_counter()
    for _ in range(iterations):
        cs_parents = list(deep_cs.parents)
    cs_time = time.perf_counter() - start_time
    
    start_time = time.perf_counter()
    for _ in range(iterations):
        bs_parents = list(deep_bs.parents)
    bs_time = time.perf_counter() - start_time
    
    print(f"   CutySoup (C++ bulk): {cs_time:.4f}s ({len(cs_parents)} parents)")
    print(f"   BeautifulSoup4 (generator): {bs_time:.4f}s ({len(bs_parents)} parents)")
    if cs_time > 0:
        print(f"   Speedup: {bs_time/cs_time:.1f}x")
    
    # Test 3: Sibling navigation
    print("\n3. Next Siblings Navigation:")
    first_section_cs = cs_soup.find('section')
    first_section_bs = bs_soup.find('section')
    
    start_time = time.perf_counter()
    for _ in range(iterations):
        cs_siblings = list(first_section_cs.next_siblings)
    cs_time = time.perf_counter() - start_time
    
    start_time = time.perf_counter()
    for _ in range(iterations):
        bs_siblings = list(first_section_bs.next_siblings)
    bs_time = time.perf_counter() - start_time
    
    print(f"   CutySoup (C++ bulk): {cs_time:.4f}s ({len(cs_siblings)} siblings)")
    print(f"   BeautifulSoup4 (generator): {bs_time:.4f}s ({len(bs_siblings)} siblings)")
    if cs_time > 0:
        print(f"   Speedup: {bs_time/cs_time:.1f}x")

if __name__ == '__main__':
    test_cpp_navigation_methods()
    test_python_api_navigation()
    benchmark_navigation_performance()