#!/usr/bin/env python3
"""
Comprehensive Performance Benchmark: CutySoup vs BeautifulSoup4
Tests all major operations, not just parsing
"""

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

def time_operation(func, iterations=5):
    """Time an operation with multiple iterations and return statistics."""
    times = []
    for _ in range(iterations):
        start = time.perf_counter()
        result = func()
        end = time.perf_counter()
        times.append((end - start) * 1000)  # Convert to milliseconds

    return {
        'avg': statistics.mean(times),
        'min': min(times),
        'max': max(times),
        'result_count': len(result) if hasattr(result, '__len__') else 1
    }

def create_complex_html():
    """Create a complex HTML document for realistic testing."""
    return """<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Performance Test Document</title>
    <style>
        .highlight { background: yellow; }
        .important { font-weight: bold; }
    </style>
</head>
<body>
    <header id="main-header" class="site-header">
        <nav class="navigation">
            <ul class="nav-list">
                <li class="nav-item active"><a href="#home">Home</a></li>
                <li class="nav-item"><a href="#about">About</a></li>
                <li class="nav-item"><a href="#contact">Contact</a></li>
            </ul>
        </nav>
    </header>

    <main class="content-area">
        <section class="hero-section" data-component="hero">
            <h1 class="hero-title">Welcome to Performance Testing</h1>
            <p class="hero-subtitle">Comprehensive benchmark suite</p>
        </section>

        """ + "".join(f"""
        <article class="post" id="post-{i}" data-id="{i}" data-category="tech">
            <header class="post-header">
                <h2 class="post-title">Article Title {i}</h2>
                <div class="post-meta">
                    <span class="author">Author {i}</span>
                    <time class="publish-date" datetime="2024-01-{i:02d}">Jan {i}, 2024</time>
                    <span class="category tech">Technology</span>
                </div>
            </header>
            <div class="post-content">
                <p class="intro highlight">Introduction paragraph for article {i} with <em>emphasis</em> and <strong class="important">important</strong> text.</p>
                <p class="body-text">Main content paragraph with substantial text content for article {i}. This paragraph contains multiple sentences to test text extraction performance.</p>
                <ul class="feature-list">
                    <li class="feature-item">Feature {i}A</li>
                    <li class="feature-item">Feature {i}B</li>
                    <li class="feature-item highlight">Feature {i}C</li>
                </ul>
                <blockquote class="quote" data-source="author-{i}">
                    "This is a sample quote for article {i} to test complex text extraction."
                </blockquote>
            </div>
            <footer class="post-footer">
                <div class="tags">
                    <span class="tag python">Python</span>
                    <span class="tag performance">Performance</span>
                    <span class="tag tag-{i}">Topic{i}</span>
                </div>
                <div class="social-share">
                    <button class="share-btn twitter" data-platform="twitter">Share on Twitter</button>
                    <button class="share-btn facebook" data-platform="facebook">Share on Facebook</button>
                </div>
            </footer>
        </article>
        """ for i in range(1, 51)) + """
    </main>

    <aside class="sidebar">
        <div class="widget recent-posts">
            <h3 class="widget-title">Recent Posts</h3>
            <ul class="recent-list">
                """ + "".join(f'<li class="recent-item"><a href="#post-{i}">Recent Article {i}</a></li>' for i in range(1, 11)) + """
            </ul>
        </div>

        <div class="widget categories">
            <h3 class="widget-title">Categories</h3>
            <ul class="category-list">
                <li class="category-item"><a href="#tech">Technology</a></li>
                <li class="category-item"><a href="#science">Science</a></li>
                <li class="category-item"><a href="#programming">Programming</a></li>
            </ul>
        </div>
    </aside>

    <footer id="main-footer" class="site-footer">
        <div class="footer-content">
            <p class="copyright">&copy; 2024 Performance Test Site</p>
            <nav class="footer-nav">
                <a href="#privacy">Privacy</a>
                <a href="#terms">Terms</a>
                <a href="#support">Support</a>
            </nav>
        </div>
    </footer>
</body>
</html>"""

def run_comprehensive_benchmark():
    print("🔥 COMPREHENSIVE PERFORMANCE BENCHMARK")
    print("=" * 60)
    print("CutySoup vs BeautifulSoup4 - All Operations")
    print("=" * 60)

    html = create_complex_html()
    print(f"Document size: {len(html):,} characters")
    print(f"Test document contains: ~50 articles, ~500 elements, complex nesting")
    print()

    # Initialize parsers
    print("⏱️  PARSING PERFORMANCE")
    print("-" * 30)

    cs_parse_time = time_operation(lambda: CutySoup(html), iterations=10)
    bs_parse_time = time_operation(lambda: BeautifulSoup(html, 'html.parser'), iterations=10)

    print(f"CutySoup parsing:     {cs_parse_time['avg']:.2f}ms ± {cs_parse_time['max']-cs_parse_time['min']:.2f}ms")
    print(f"BeautifulSoup parsing: {bs_parse_time['avg']:.2f}ms ± {bs_parse_time['max']-bs_parse_time['min']:.2f}ms")
    parse_speedup = bs_parse_time['avg'] / cs_parse_time['avg']
    print(f"📊 Parsing speedup: {parse_speedup:.1f}x {'🚀' if parse_speedup > 1 else '🐌'}")
    print()

    # Create parsed instances for other tests
    cs_soup = CutySoup(html)
    bs_soup = BeautifulSoup(html, 'html.parser')

    # Test Results Storage
    results = []

    # 1. FIND OPERATIONS
    print("🔍 FIND OPERATIONS")
    print("-" * 30)

    # Simple tag search
    cs_time = time_operation(lambda: cs_soup.find_all('article'))
    bs_time = time_operation(lambda: bs_soup.find_all('article'))
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"find_all('article'):   CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('find_all(tag)', speedup))

    # Class search
    cs_time = time_operation(lambda: cs_soup.find_all(class_='highlight'))
    bs_time = time_operation(lambda: bs_soup.find_all(class_='highlight'))
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"find_all(class_='highlight'): CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('find_all(class)', speedup))

    # ID search
    cs_time = time_operation(lambda: cs_soup.find(id='main-header'))
    bs_time = time_operation(lambda: bs_soup.find(id='main-header'))
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"find(id='main-header'): CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('find(id)', speedup))

    # Attribute search
    cs_time = time_operation(lambda: cs_soup.find_all(attrs={'data-category': 'tech'}))
    bs_time = time_operation(lambda: bs_soup.find_all(attrs={'data-category': 'tech'}))
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"find_all(attrs): CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('find_all(attrs)', speedup))

    # Regex search
    pattern = re.compile(r'post-\d+')
    cs_time = time_operation(lambda: cs_soup.find_all(id=pattern))
    bs_time = time_operation(lambda: bs_soup.find_all(id=pattern))
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"find_all(regex): CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('find_all(regex)', speedup))
    print()

    # 2. CSS SELECTORS
    print("🎨 CSS SELECTORS")
    print("-" * 30)

    # Simple CSS selector
    cs_time = time_operation(lambda: cs_soup.select('article.post'))
    bs_time = time_operation(lambda: bs_soup.select('article.post'))
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"select('article.post'): CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('CSS simple', speedup))

    # Complex CSS selector
    cs_time = time_operation(lambda: cs_soup.select('article .highlight'))
    bs_time = time_operation(lambda: bs_soup.select('article .highlight'))
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"select('article .highlight'): CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('CSS complex', speedup))

    # Attribute CSS selector
    cs_time = time_operation(lambda: cs_soup.select('[data-category="tech"]'))
    bs_time = time_operation(lambda: bs_soup.select('[data-category="tech"]'))
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"select('[data-category=\"tech\"]'): CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('CSS attribute', speedup))
    print()

    # 3. TEXT EXTRACTION
    print("📝 TEXT EXTRACTION")
    print("-" * 30)

    # Get all text
    cs_time = time_operation(lambda: cs_soup.get_text())
    bs_time = time_operation(lambda: bs_soup.get_text())
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"get_text(): CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('get_text()', speedup))

    # Get text with separator
    cs_time = time_operation(lambda: cs_soup.get_text(separator=' | '))
    bs_time = time_operation(lambda: bs_soup.get_text(separator=' | '))
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"get_text(separator): CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('get_text(sep)', speedup))

    # Find by string content
    cs_time = time_operation(lambda: cs_soup.find_all(string=re.compile('Article Title')))
    bs_time = time_operation(lambda: bs_soup.find_all(string=re.compile('Article Title')))
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"find_all(string): CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('find_all(string)', speedup))
    print()

    # 4. TREE NAVIGATION
    print("🌳 TREE NAVIGATION")
    print("-" * 30)

    # Get first article for navigation tests
    cs_article = cs_soup.find('article')
    bs_article = bs_soup.find('article')

    # Children iteration
    cs_time = time_operation(lambda: list(cs_article.children))
    bs_time = time_operation(lambda: list(bs_article.children))
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"list(children): CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('children', speedup))

    # Descendants iteration
    cs_time = time_operation(lambda: len(list(cs_article.descendants)))
    bs_time = time_operation(lambda: len(list(bs_article.descendants)))
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"list(descendants): CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('descendants', speedup))

    # Parent access
    cs_time = time_operation(lambda: cs_article.parent)
    bs_time = time_operation(lambda: bs_article.parent)
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"parent access: CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('parent', speedup))
    print()

    # 5. ATTRIBUTE ACCESS
    print("🏷️  ATTRIBUTE ACCESS")
    print("-" * 30)

    # Get attribute
    cs_time = time_operation(lambda: [art.get('data-id') for art in cs_soup.find_all('article')])
    bs_time = time_operation(lambda: [art.get('data-id') for art in bs_soup.find_all('article')])
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"get('data-id') bulk: CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('get(attr)', speedup))

    # Has attribute
    cs_time = time_operation(lambda: [art.has_attr('data-category') for art in cs_soup.find_all('article')])
    bs_time = time_operation(lambda: [art.has_attr('data-category') for art in bs_soup.find_all('article')])
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"has_attr() bulk: CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('has_attr()', speedup))
    print()

    # 6. COMPLEX OPERATIONS
    print("⚡ COMPLEX OPERATIONS")
    print("-" * 30)

    # Complex query combining multiple operations
    def complex_cs_operation():
        articles = cs_soup.find_all('article', class_='post')
        return [
            {
                'title': art.find('h2', class_='post-title').get_text(),
                'author': art.find('span', class_='author').get_text(),
                'tags': [tag.get_text() for tag in art.find_all('span', class_='tag')],
                'highlighted': len(art.find_all(class_='highlight'))
            }
            for art in articles[:10]  # First 10 articles
        ]

    def complex_bs_operation():
        articles = bs_soup.find_all('article', class_='post')
        return [
            {
                'title': art.find('h2', class_='post-title').get_text(),
                'author': art.find('span', class_='author').get_text(),
                'tags': [tag.get_text() for tag in art.find_all('span', class_='tag')],
                'highlighted': len(art.find_all(class_='highlight'))
            }
            for art in articles[:10]  # First 10 articles
        ]

    cs_time = time_operation(complex_cs_operation)
    bs_time = time_operation(complex_bs_operation)
    speedup = bs_time['avg'] / cs_time['avg']
    print(f"Complex extraction: CS={cs_time['avg']:.2f}ms, BS={bs_time['avg']:.2f}ms, {speedup:.1f}x {'🚀' if speedup > 1 else '🐌'}")
    results.append(('Complex ops', speedup))
    print()

    # SUMMARY
    print("📊 OVERALL PERFORMANCE SUMMARY")
    print("=" * 60)

    faster_count = sum(1 for _, speedup in results if speedup > 1.0)
    slower_count = sum(1 for _, speedup in results if speedup < 1.0)
    equal_count = sum(1 for _, speedup in results if speedup == 1.0)

    avg_speedup = statistics.mean([speedup for _, speedup in results])

    print(f"Operations tested: {len(results)}")
    print(f"CutySoup faster: {faster_count} operations")
    print(f"CutySoup slower: {slower_count} operations")
    print(f"Equal performance: {equal_count} operations")
    print(f"Average speedup: {avg_speedup:.1f}x")
    print()

    print("🏆 PERFORMANCE BREAKDOWN:")

    # Categorize results
    excellent = [(name, speedup) for name, speedup in results if speedup >= 2.0]
    good = [(name, speedup) for name, speedup in results if 1.2 <= speedup < 2.0]
    competitive = [(name, speedup) for name, speedup in results if 0.8 <= speedup < 1.2]
    slower = [(name, speedup) for name, speedup in results if speedup < 0.8]

    if excellent:
        print(f"🚀 EXCELLENT (2x+ faster): {len(excellent)} operations")
        for name, speedup in excellent:
            print(f"   {name}: {speedup:.1f}x")

    if good:
        print(f"✅ GOOD (1.2x+ faster): {len(good)} operations")
        for name, speedup in good:
            print(f"   {name}: {speedup:.1f}x")

    if competitive:
        print(f"🟡 COMPETITIVE (±20%): {len(competitive)} operations")
        for name, speedup in competitive:
            print(f"   {name}: {speedup:.1f}x")

    if slower:
        print(f"🐌 SLOWER: {len(slower)} operations")
        for name, speedup in slower:
            print(f"   {name}: {speedup:.1f}x")

    print()
    print("=" * 60)

    if avg_speedup >= 1.5:
        verdict = "🏆 DRAMATICALLY FASTER - Significant performance advantage"
    elif avg_speedup >= 1.2:
        verdict = "🚀 CONSISTENTLY FASTER - Clear performance wins"
    elif avg_speedup >= 0.8:
        verdict = "✅ COMPETITIVE - Similar performance with some wins"
    else:
        verdict = "🐌 SLOWER - Performance needs improvement"

    print(f"VERDICT: {verdict}")
    print(f"OVERALL SPEEDUP: {avg_speedup:.1f}x average across all operations")
    print("=" * 60)

if __name__ == "__main__":
    run_comprehensive_benchmark()