#!/usr/bin/env python3
"""
Comprehensive CutySoup vs BeautifulSoup4 Performance Comparison
"""

import time
import statistics
from cutysoup import CutySoup
from bs4 import BeautifulSoup

def benchmark_parsing_performance():
    print("🏁 CUTYSOUP vs BEAUTIFULSOUP4 - COMPREHENSIVE BENCHMARK")
    print("=" * 65)
    
    # Create a realistic, large HTML document for testing
    base_html = """<!DOCTYPE html>
<html>
<head>
    <title>Performance Benchmark Document</title>
    <meta charset="utf-8">
    <meta name="description" content="Testing document for performance comparison">
    <link rel="stylesheet" href="styles.css">
    <script src="script.js"></script>
</head>
<body>
    <header class="site-header">
        <nav class="navigation">
            <ul class="nav-menu">
                <li><a href="/">Home</a></li>
                <li><a href="/about">About</a></li>
                <li><a href="/contact">Contact</a></li>
            </ul>
        </nav>
    </header>
    <main class="content">
"""
    
    # Add many articles to create a substantial document
    article_template = """
        <article class="post article-{id}" data-id="{id}" data-category="tech">
            <header class="article-header">
                <h1 class="title">Article Title {id}</h1>
                <div class="metadata">
                    <span class="author">Author {id}</span>
                    <time class="publish-date" datetime="2024-01-{id}">January {id}, 2024</time>
                    <div class="tags">
                        <span class="tag primary">Python</span>
                        <span class="tag secondary">Performance</span>
                        <span class="tag tertiary">HTML</span>
                    </div>
                </div>
            </header>
            <div class="article-content">
                <p class="intro">This is the introduction paragraph for article {id}. It contains some introductory text to give context.</p>
                <div class="main-content">
                    <p class="paragraph">First main paragraph with substantial content for article {id}. This paragraph contains detailed information.</p>
                    <p class="paragraph">Second main paragraph continues the discussion with more detailed content for article {id}.</p>
                    <ul class="feature-list">
                        <li class="feature">Feature A for article {id}</li>
                        <li class="feature">Feature B for article {id}</li>
                        <li class="feature">Feature C for article {id}</li>
                    </ul>
                </div>
                <footer class="article-footer">
                    <div class="social-sharing">
                        <a href="#" class="share-button facebook">Facebook</a>
                        <a href="#" class="share-button twitter">Twitter</a>
                        <a href="#" class="share-button linkedin">LinkedIn</a>
                    </div>
                </footer>
            </div>
        </article>
    """
    
    # Build large document
    articles = ""
    num_articles = 100  # Substantial document
    for i in range(1, num_articles + 1):
        articles += article_template.format(id=i)
    
    full_html = base_html + articles + """
    </main>
    <footer class="site-footer">
        <div class="footer-content">
            <p class="copyright">© 2024 Performance Test Site</p>
            <ul class="footer-links">
                <li><a href="/privacy">Privacy</a></li>
                <li><a href="/terms">Terms</a></li>
                <li><a href="/sitemap">Sitemap</a></li>
            </ul>
        </div>
    </footer>
</body>
</html>
    """
    
    print(f"📄 Test Document: {len(full_html):,} characters")
    
    # Parse with both libraries
    print("\n🔄 Parsing Performance:")
    print("-" * 30)
    
    # CutySoup parsing
    runs = 10
    cs_parse_times = []
    for _ in range(runs):
        start = time.perf_counter()
        cs_soup = CutySoup(full_html)
        cs_parse_times.append(time.perf_counter() - start)
    
    cs_parse_avg = statistics.mean(cs_parse_times) * 1000
    print(f"CutySoup parsing:     {cs_parse_avg:.2f}ms avg")
    
    # BeautifulSoup4 parsing
    bs_parse_times = []
    for _ in range(runs):
        start = time.perf_counter()
        bs_soup = BeautifulSoup(full_html, 'html.parser')
        bs_parse_times.append(time.perf_counter() - start)
    
    bs_parse_avg = statistics.mean(bs_parse_times) * 1000
    print(f"BeautifulSoup4 parsing: {bs_parse_avg:.2f}ms avg")
    print(f"Parsing speedup:      {bs_parse_avg/cs_parse_avg:.1f}x faster")
    
    # Now benchmark operations on parsed documents
    print(f"\n📊 Element count: ~{len(cs_soup.find_all(True)):,} total elements")
    
    def benchmark_operation(name, cs_operation, bs_operation, iterations=100):
        print(f"\n🧪 {name}:")
        print("-" * 30)
        
        # Benchmark CutySoup
        cs_times = []
        cs_result = None
        for _ in range(iterations):
            start = time.perf_counter()
            cs_result = cs_operation()
            cs_times.append(time.perf_counter() - start)
        
        cs_avg = statistics.mean(cs_times) * 1000
        cs_count = len(cs_result) if isinstance(cs_result, list) else (1 if cs_result else 0)
        
        # Benchmark BeautifulSoup4
        bs_times = []
        bs_result = None
        for _ in range(iterations):
            start = time.perf_counter()
            bs_result = bs_operation()
            bs_times.append(time.perf_counter() - start)
        
        bs_avg = statistics.mean(bs_times) * 1000
        bs_count = len(bs_result) if isinstance(bs_result, list) else (1 if bs_result else 0)
        
        speedup = bs_avg / cs_avg if cs_avg > 0 else 0
        
        print(f"CutySoup:       {cs_avg:.3f}ms avg ({cs_count:,} results)")
        print(f"BeautifulSoup4: {bs_avg:.3f}ms avg ({bs_count:,} results)")
        print(f"Speedup:        {speedup:.1f}x faster")
        
        if cs_count != bs_count:
            print(f"⚠️  Result count mismatch!")
        
        return speedup, cs_avg, bs_avg
    
    # Test 1: Find all paragraphs
    speedup1, _, _ = benchmark_operation(
        "Find All Paragraphs",
        lambda: cs_soup.find_all("p"),
        lambda: bs_soup.find_all("p")
    )
    
    # Test 2: Find by class
    speedup2, _, _ = benchmark_operation(
        "Find by Class (.article-header)",
        lambda: cs_soup.find_all(class_="article-header"),
        lambda: bs_soup.find_all(class_="article-header")
    )
    
    # Test 3: Find by attributes
    speedup3, _, _ = benchmark_operation(
        "Find by Attribute (data-category='tech')",
        lambda: cs_soup.find_all(attrs={"data-category": "tech"}),
        lambda: bs_soup.find_all(attrs={"data-category": "tech"})
    )
    
    # Test 4: CSS Selectors
    speedup4, _, _ = benchmark_operation(
        "CSS Selector (article .main-content p)",
        lambda: cs_soup.select("article .main-content p"),
        lambda: bs_soup.select("article .main-content p")
    )
    
    # Test 5: Text extraction
    first_article_cs = cs_soup.find("article")
    first_article_bs = bs_soup.find("article")
    
    speedup5, _, _ = benchmark_operation(
        "Text Extraction (article.get_text())",
        lambda: first_article_cs.get_text(),
        lambda: first_article_bs.get_text(),
        iterations=500
    )
    
    # Test 6: Navigation
    speedup6, _, _ = benchmark_operation(
        "Navigation (list all descendants)",
        lambda: list(first_article_cs.descendants),
        lambda: list(first_article_bs.descendants),
        iterations=200
    )
    
    # Test 7: Complex find with multiple criteria
    speedup7, _, _ = benchmark_operation(
        "Complex Find (span with multiple classes)",
        lambda: cs_soup.find_all("span", class_=["tag", "primary"]),
        lambda: bs_soup.find_all("span", class_=["tag", "primary"])
    )
    
    # Summary
    print("\n📈 PERFORMANCE SUMMARY")
    print("=" * 40)
    
    operations = [
        ("Document Parsing", bs_parse_avg/cs_parse_avg),
        ("Find All Elements", speedup1),
        ("Find by Class", speedup2), 
        ("Find by Attributes", speedup3),
        ("CSS Selectors", speedup4),
        ("Text Extraction", speedup5),
        ("Navigation", speedup6),
        ("Complex Find", speedup7)
    ]
    
    total_speedup = 1
    for name, speedup in operations:
        total_speedup *= speedup
        color = "🚀" if speedup >= 5 else "⚡" if speedup >= 2 else "✅" if speedup >= 1.1 else "⚠️"
        print(f"{color} {name:20} {speedup:6.1f}x faster")
    
    # Calculate geometric mean for overall performance
    geometric_mean = total_speedup ** (1.0 / len(operations))
    
    print(f"\n🎯 OVERALL PERFORMANCE:")
    print(f"   Geometric Mean: {geometric_mean:.1f}x faster than BeautifulSoup4")
    
    # Performance tier classification
    if geometric_mean >= 10:
        tier = "🔥 BLAZING FAST"
    elif geometric_mean >= 5:
        tier = "🚀 VERY FAST" 
    elif geometric_mean >= 2:
        tier = "⚡ FAST"
    elif geometric_mean >= 1.5:
        tier = "✅ FASTER"
    else:
        tier = "⚠️  SIMILAR"
    
    print(f"   Performance Tier: {tier}")
    
    return geometric_mean, operations

if __name__ == "__main__":
    overall_speedup, detailed_results = benchmark_parsing_performance()