#!/usr/bin/env python3
"""
Test FastTree implementation against BeautifulSoup4 for performance and functionality
"""

import time
import sys
import os
from typing import List, Tuple

# Test HTML content - realistic e-commerce page
TEST_HTML = """
<!DOCTYPE html>
<html>
<head>
    <title>E-commerce Test Page</title>
    <meta charset="utf-8">
</head>
<body>
    <nav class="main-nav">
        <a href="/" id="home-link">Home</a>
        <a href="/products" class="nav-link">Products</a>
        <a href="/about" class="nav-link">About</a>
        <a href="/contact" class="nav-link">Contact</a>
    </nav>
    
    <main class="content">
        <h1>Featured Products</h1>
        
        <div class="product-grid">
            <div class="product-card" data-id="1">
                <img src="/images/laptop.jpg" alt="Gaming Laptop" class="product-image">
                <div class="product-info">
                    <h2 class="product-name">High-Performance Gaming Laptop</h2>
                    <p class="product-description">Powerful laptop for gaming and professional work</p>
                    <div class="price-container">
                        <span class="current-price">$1299.99</span>
                        <span class="original-price">$1599.99</span>
                        <span class="discount">20% OFF</span>
                    </div>
                    <div class="rating">
                        <span class="stars" data-rating="4.5">★★★★☆</span>
                        <span class="review-count">(127 reviews)</span>
                    </div>
                    <button class="add-to-cart" data-product="1">Add to Cart</button>
                </div>
            </div>
            
            <div class="product-card" data-id="2">
                <img src="/images/mouse.jpg" alt="Wireless Mouse" class="product-image">
                <div class="product-info">
                    <h2 class="product-name">Wireless Gaming Mouse</h2>
                    <p class="product-description">Precision gaming mouse with RGB lighting</p>
                    <div class="price-container">
                        <span class="current-price">$79.99</span>
                    </div>
                    <div class="rating">
                        <span class="stars" data-rating="4.8">★★★★★</span>
                        <span class="review-count">(89 reviews)</span>
                    </div>
                    <button class="add-to-cart" data-product="2">Add to Cart</button>
                </div>
            </div>
            
            <div class="product-card" data-id="3">
                <img src="/images/keyboard.jpg" alt="Mechanical Keyboard" class="product-image">
                <div class="product-info">
                    <h2 class="product-name">Mechanical Gaming Keyboard</h2>
                    <p class="product-description">Premium mechanical keyboard with backlit keys</p>
                    <div class="price-container">
                        <span class="current-price">$129.99</span>
                        <span class="original-price">$149.99</span>
                        <span class="discount">13% OFF</span>
                    </div>
                    <div class="rating">
                        <span class="stars" data-rating="4.7">★★★★★</span>
                        <span class="review-count">(203 reviews)</span>
                    </div>
                    <button class="add-to-cart" data-product="3">Add to Cart</button>
                </div>
            </div>
        </div>
        
        <section class="categories">
            <h2>Shop by Category</h2>
            <div class="category-list">
                <a href="/category/laptops" class="category-link">Laptops</a>
                <a href="/category/accessories" class="category-link">Accessories</a>
                <a href="/category/gaming" class="category-link">Gaming</a>
                <a href="/category/office" class="category-link">Office</a>
            </div>
        </section>
        
        <footer class="site-footer">
            <div class="footer-content">
                <div class="footer-section">
                    <h3>Customer Service</h3>
                    <ul>
                        <li><a href="/support">Support</a></li>
                        <li><a href="/returns">Returns</a></li>
                        <li><a href="/shipping">Shipping Info</a></li>
                    </ul>
                </div>
                <div class="footer-section">
                    <h3>Company</h3>
                    <ul>
                        <li><a href="/about">About Us</a></li>
                        <li><a href="/careers">Careers</a></li>
                        <li><a href="/press">Press</a></li>
                    </ul>
                </div>
            </div>
        </footer>
    </main>
</body>
</html>
""" * 10  # Make it bigger for more realistic testing

def test_cutysoup_basic():
    """Test basic CutySoup functionality"""
    print("🔍 Testing CutySoup FastTree Implementation...")
    
    try:
        # Test new FastTree implementation
        import cutysoup._cutysoup as _cutysoup
        
        print("✓ Successfully imported _cutysoup C++ extension")
        
        # Create tree and test basic functionality
        tree = _cutysoup.Tree(TEST_HTML)
        print(f"✓ Created tree with {tree.get_node_count()} nodes")
        
        # Test root access
        root = tree.get_root()
        print(f"✓ Got root node: {root.get_name()}")
        
        # Test tag-based searches
        titles = tree.find_all_by_tag("title")
        print(f"✓ Found {len(titles)} title tags")
        
        h1_tags = tree.find_all_by_tag("h1")
        print(f"✓ Found {len(h1_tags)} h1 tags")
        if h1_tags:
            print(f"  H1 text: '{h1_tags[0].get_text()}'")
        
        h2_tags = tree.find_all_by_tag("h2")
        print(f"✓ Found {len(h2_tags)} h2 tags")
        
        # Test class-based searches  
        products = tree.find_all_by_class("product-card")
        print(f"✓ Found {len(products)} products by class")
        
        nav_links = tree.find_all_by_class("nav-link")
        print(f"✓ Found {len(nav_links)} nav links by class")
        
        # Test ID-based searches
        home_links = tree.find_all_by_id("home-link") 
        print(f"✓ Found {len(home_links)} elements with ID 'home-link'")
        
        # Test bulk operations
        all_links = tree.extract_all_hrefs()
        print(f"✓ Extracted {len(all_links)} href attributes")
        
        all_images = tree.extract_all_src()
        print(f"✓ Extracted {len(all_images)} src attributes")
        
        product_names = tree.extract_all_text_by_tag("h2")
        print(f"✓ Extracted {len(product_names)} product names")
        
        # Test CSS selectors
        try:
            price_elements = tree.select(".current-price")
            print(f"✓ CSS selector found {len(price_elements)} price elements")
            
            first_product = tree.select_one(".product-card")
            if first_product:
                print(f"✓ First product: {first_product.get_attribute('data-id')}")
        except Exception as e:
            print(f"⚠ CSS selector not fully implemented: {e}")
        
        print("🎉 Basic CutySoup functionality test PASSED!")
        return True
        
    except Exception as e:
        print(f"❌ CutySoup test failed: {e}")
        import traceback
        traceback.print_exc()
        return False


def test_beautifulsoup4():
    """Test BeautifulSoup4 for comparison"""
    print("\n🐌 Testing BeautifulSoup4 for comparison...")
    
    try:
        from bs4 import BeautifulSoup
        
        soup = BeautifulSoup(TEST_HTML, 'html.parser')
        print("✓ Created BeautifulSoup4 instance")
        
        # Test equivalent operations
        titles = soup.find_all("title")
        print(f"✓ Found {len(titles)} title tags")
        
        h1_tags = soup.find_all("h1")
        print(f"✓ Found {len(h1_tags)} h1 tags")
        
        h2_tags = soup.find_all("h2")
        print(f"✓ Found {len(h2_tags)} h2 tags")
        
        products = soup.find_all(class_="product-card")
        print(f"✓ Found {len(products)} products by class")
        
        nav_links = soup.find_all(class_="nav-link")
        print(f"✓ Found {len(nav_links)} nav links by class")
        
        home_link = soup.find(id="home-link")
        print(f"✓ Found home link: {home_link is not None}")
        
        # Bulk operations
        all_links = [a.get('href') for a in soup.find_all('a') if a.get('href')]
        print(f"✓ Extracted {len(all_links)} href attributes")
        
        all_images = [img.get('src') for img in soup.find_all('img') if img.get('src')]
        print(f"✓ Extracted {len(all_images)} src attributes")
        
        product_names = [h2.get_text() for h2 in soup.find_all('h2')]
        print(f"✓ Extracted {len(product_names)} product names")
        
        price_elements = soup.select(".current-price")
        print(f"✓ CSS selector found {len(price_elements)} price elements")
        
        print("✓ BeautifulSoup4 functionality test PASSED!")
        return True
        
    except Exception as e:
        print(f"❌ BeautifulSoup4 test failed: {e}")
        return False


def benchmark_parsing(iterations=100):
    """Benchmark parsing performance"""
    print(f"\n⚡ Benchmarking Parsing Performance ({iterations} iterations)...")
    
    results = {}
    
    # Benchmark CutySoup
    print("Testing CutySoup parsing speed...")
    try:
        import cutysoup._cutysoup as _cutysoup
        
        start_time = time.time()
        for _ in range(iterations):
            tree = _cutysoup.Tree(TEST_HTML)
            # Force some basic operations to ensure parsing is complete
            tree.get_node_count()
        cutysoup_time = time.time() - start_time
        
        results['cutysoup_parse'] = cutysoup_time
        print(f"✓ CutySoup: {cutysoup_time:.4f}s ({cutysoup_time*1000/iterations:.2f}ms per parse)")
        
    except Exception as e:
        print(f"❌ CutySoup benchmark failed: {e}")
        results['cutysoup_parse'] = float('inf')
    
    # Benchmark BeautifulSoup4
    print("Testing BeautifulSoup4 parsing speed...")
    try:
        from bs4 import BeautifulSoup
        
        start_time = time.time()
        for _ in range(iterations):
            soup = BeautifulSoup(TEST_HTML, 'html.parser')
            # Force some basic operations 
            len(list(soup.descendants))
        bs4_time = time.time() - start_time
        
        results['bs4_parse'] = bs4_time
        print(f"✓ BeautifulSoup4: {bs4_time:.4f}s ({bs4_time*1000/iterations:.2f}ms per parse)")
        
    except Exception as e:
        print(f"❌ BeautifulSoup4 benchmark failed: {e}")
        results['bs4_parse'] = float('inf')
    
    # Calculate speedup
    if results.get('cutysoup_parse', float('inf')) < float('inf') and results.get('bs4_parse', float('inf')) < float('inf'):
        speedup = results['bs4_parse'] / results['cutysoup_parse']
        print(f"🚀 CutySoup is {speedup:.1f}x FASTER than BeautifulSoup4 for parsing!")
    
    return results


def benchmark_searching(iterations=1000):
    """Benchmark search operations"""
    print(f"\n🔍 Benchmarking Search Performance ({iterations} iterations)...")
    
    results = {}
    
    # Prepare instances
    try:
        import cutysoup._cutysoup as _cutysoup
        cutysoup_tree = _cutysoup.Tree(TEST_HTML)
        print("✓ CutySoup tree ready")
    except:
        print("❌ CutySoup not available")
        cutysoup_tree = None
    
    try:
        from bs4 import BeautifulSoup
        bs4_soup = BeautifulSoup(TEST_HTML, 'html.parser')
        print("✓ BeautifulSoup4 soup ready")
    except:
        print("❌ BeautifulSoup4 not available")
        bs4_soup = None
    
    # Benchmark tag searches
    if cutysoup_tree:
        start_time = time.time()
        for _ in range(iterations):
            cutysoup_tree.find_all_by_tag("div")
        cutysoup_search_time = time.time() - start_time
        results['cutysoup_search'] = cutysoup_search_time
        print(f"✓ CutySoup tag search: {cutysoup_search_time:.4f}s ({cutysoup_search_time*1000/iterations:.3f}ms per search)")
    
    if bs4_soup:
        start_time = time.time()
        for _ in range(iterations):
            bs4_soup.find_all("div")
        bs4_search_time = time.time() - start_time
        results['bs4_search'] = bs4_search_time
        print(f"✓ BeautifulSoup4 tag search: {bs4_search_time:.4f}s ({bs4_search_time*1000/iterations:.3f}ms per search)")
    
    # Benchmark class searches
    if cutysoup_tree:
        start_time = time.time()
        for _ in range(iterations):
            cutysoup_tree.find_all_by_class("product-card")
        cutysoup_class_time = time.time() - start_time
        results['cutysoup_class'] = cutysoup_class_time
        print(f"✓ CutySoup class search: {cutysoup_class_time:.4f}s ({cutysoup_class_time*1000/iterations:.3f}ms per search)")
    
    if bs4_soup:
        start_time = time.time()
        for _ in range(iterations):
            bs4_soup.find_all(class_="product-card")
        bs4_class_time = time.time() - start_time
        results['bs4_class'] = bs4_class_time
        print(f"✓ BeautifulSoup4 class search: {bs4_class_time:.4f}s ({bs4_class_time*1000/iterations:.3f}ms per search)")
    
    # Benchmark bulk operations
    if cutysoup_tree:
        start_time = time.time()
        for _ in range(iterations):
            cutysoup_tree.extract_all_hrefs()
        cutysoup_bulk_time = time.time() - start_time
        results['cutysoup_bulk'] = cutysoup_bulk_time
        print(f"✓ CutySoup bulk href extraction: {cutysoup_bulk_time:.4f}s ({cutysoup_bulk_time*1000/iterations:.3f}ms per extraction)")
    
    if bs4_soup:
        start_time = time.time()
        for _ in range(iterations):
            [a.get('href') for a in bs4_soup.find_all('a') if a.get('href')]
        bs4_bulk_time = time.time() - start_time
        results['bs4_bulk'] = bs4_bulk_time
        print(f"✓ BeautifulSoup4 bulk href extraction: {bs4_bulk_time:.4f}s ({bs4_bulk_time*1000/iterations:.3f}ms per extraction)")
    
    # Calculate speedups
    comparisons = [
        ('search', 'Tag Search'),
        ('class', 'Class Search'), 
        ('bulk', 'Bulk Operations')
    ]
    
    for suffix, name in comparisons:
        cutysoup_key = f'cutysoup_{suffix}'
        bs4_key = f'bs4_{suffix}'
        
        if cutysoup_key in results and bs4_key in results:
            speedup = results[bs4_key] / results[cutysoup_key]
            if speedup > 1:
                print(f"🚀 {name}: CutySoup is {speedup:.1f}x FASTER than BeautifulSoup4")
            else:
                print(f"🐌 {name}: CutySoup is {1/speedup:.1f}x slower than BeautifulSoup4")
    
    return results


def main():
    """Run comprehensive performance tests"""
    print("🚀 CutySoup FastTree Performance Test Suite")
    print("=" * 60)
    
    # Test basic functionality first
    cutysoup_works = test_cutysoup_basic()
    bs4_works = test_beautifulsoup4()
    
    if not cutysoup_works:
        print("❌ CutySoup basic functionality failed, skipping benchmarks")
        return False
    
    if not bs4_works:
        print("⚠ BeautifulSoup4 not available, skipping comparisons")
    
    # Run performance benchmarks
    print("\n" + "=" * 60)
    print("⚡ PERFORMANCE BENCHMARKS")
    print("=" * 60)
    
    parse_results = benchmark_parsing(100)
    search_results = benchmark_searching(1000)
    
    # Summary
    print("\n" + "=" * 60)
    print("📊 PERFORMANCE SUMMARY")
    print("=" * 60)
    
    if cutysoup_works and bs4_works:
        overall_cutysoup = (
            parse_results.get('cutysoup_parse', 0) +
            search_results.get('cutysoup_search', 0) +
            search_results.get('cutysoup_class', 0) +
            search_results.get('cutysoup_bulk', 0)
        )
        
        overall_bs4 = (
            parse_results.get('bs4_parse', 0) +
            search_results.get('bs4_search', 0) +
            search_results.get('bs4_class', 0) + 
            search_results.get('bs4_bulk', 0)
        )
        
        if overall_cutysoup > 0 and overall_bs4 > 0:
            overall_speedup = overall_bs4 / overall_cutysoup
            print(f"🎯 OVERALL: CutySoup is {overall_speedup:.1f}x faster than BeautifulSoup4")
            
            if overall_speedup >= 2.0:
                print("🏆 EXCELLENT! CutySoup delivers significant performance improvements!")
            elif overall_speedup >= 1.5:
                print("✅ GOOD! CutySoup shows meaningful performance gains!")
            elif overall_speedup >= 1.1:
                print("📈 MODERATE improvement over BeautifulSoup4")
            else:
                print("⚠️ Performance is similar to BeautifulSoup4")
    
    print("\n✨ Test suite complete!")
    return cutysoup_works


if __name__ == "__main__":
    success = main()
    sys.exit(0 if success else 1)