"""
Unit tests for blackreach/detection.py

Tests CAPTCHA, login, paywall, and rate limit detection.
"""

import pytest
from blackreach.detection import SiteDetector, DetectionResult
from blackreach.exceptions import (
    CaptchaError,
    LoginRequiredError,
    PaywallError,
    RateLimitError,
    AccessDeniedError,
)


# =============================================================================
# Fixtures
# =============================================================================

@pytest.fixture
def detector():
    """Create detector instance."""
    return SiteDetector()


@pytest.fixture
def recaptcha_html():
    """HTML with reCAPTCHA."""
    return """
    <html>
    <head>
        <script src="https://www.google.com/recaptcha/api.js"></script>
    </head>
    <body>
        <div class="g-recaptcha" data-sitekey="6LcXXXXXXXXX"></div>
        <p>Please verify you're not a robot</p>
    </body>
    </html>
    """


@pytest.fixture
def hcaptcha_html():
    """HTML with hCaptcha."""
    return """
    <html>
    <head>
        <script src="https://hcaptcha.com/1/api.js"></script>
    </head>
    <body>
        <div class="h-captcha" data-sitekey="xxx"></div>
    </body>
    </html>
    """


@pytest.fixture
def cloudflare_html():
    """HTML with Cloudflare challenge."""
    return """
    <html>
    <head>
        <title>Just a moment...</title>
        <script src="https://challenges.cloudflare.com/turnstile/v0/api.js"></script>
    </head>
    <body>
        <div id="cf-challenge-running">
            <div class="cf-turnstile"></div>
        </div>
    </body>
    </html>
    """


@pytest.fixture
def login_html():
    """HTML with login form."""
    return """
    <html>
    <head><title>Sign In</title></head>
    <body>
        <h1>Sign in to continue</h1>
        <form action="/login">
            <input type="email" name="email" placeholder="Email">
            <input type="password" name="password" placeholder="Password">
            <button type="submit">Log In</button>
        </form>
    </body>
    </html>
    """


@pytest.fixture
def paywall_html():
    """HTML with paywall."""
    return """
    <html>
    <body>
        <article class="premium-content">
            <h1>Premium Article</h1>
            <div class="paywall-overlay" style="filter: blur(5px)">
                <p>This content is blurred...</p>
            </div>
            <div class="subscribe-wall">
                <h2>Subscribe to read this article</h2>
                <p>Unlock this article with a subscription</p>
            </div>
        </article>
    </body>
    </html>
    """


@pytest.fixture
def rate_limit_html():
    """HTML for rate limited response."""
    return """
    <html>
    <body>
        <h1>Too Many Requests</h1>
        <p>You have been rate limited. Please try again in 60 seconds.</p>
    </body>
    </html>
    """


@pytest.fixture
def access_denied_html():
    """HTML for access denied."""
    return """
    <html>
    <body>
        <h1>403 Forbidden</h1>
        <p>Access denied. You don't have permission to view this page.</p>
    </body>
    </html>
    """


@pytest.fixture
def normal_html():
    """Normal page without any blockers."""
    return """
    <html>
    <head><title>Normal Page</title></head>
    <body>
        <h1>Welcome</h1>
        <p>This is a normal page with no special conditions.</p>
        <a href="/other">Link</a>
    </body>
    </html>
    """


# =============================================================================
# CAPTCHA Detection Tests
# =============================================================================

class TestCaptchaDetection:
    """Tests for CAPTCHA detection."""

    def test_detect_recaptcha(self, detector, recaptcha_html):
        """Detects reCAPTCHA."""
        result = detector.detect_captcha(recaptcha_html)

        assert result.detected is True
        assert result.condition == "captcha"
        assert result.confidence >= 0.5
        assert result.details == "reCAPTCHA"

    def test_detect_hcaptcha(self, detector, hcaptcha_html):
        """Detects hCaptcha."""
        result = detector.detect_captcha(hcaptcha_html)

        assert result.detected is True
        assert result.condition == "captcha"
        assert result.details == "hCaptcha"

    def test_detect_cloudflare(self, detector, cloudflare_html):
        """Detects Cloudflare challenge."""
        result = detector.detect_captcha(cloudflare_html)

        assert result.detected is True
        assert result.condition == "captcha"
        assert result.details == "Cloudflare"

    def test_no_captcha_on_normal_page(self, detector, normal_html):
        """No false positive on normal page."""
        result = detector.detect_captcha(normal_html)

        assert result.detected is False
        assert result.condition is None

    def test_captcha_script_detection(self, detector):
        """Detects CAPTCHA by script URL."""
        html = '<script src="https://www.google.com/recaptcha/api2/anchor"></script>'
        result = detector.detect_captcha(html)

        assert result.detected is True
        assert any("Script" in i for i in result.indicators)

    def test_captcha_sitekey_detection(self, detector):
        """Detects CAPTCHA by sitekey attribute."""
        html = '<div data-sitekey="abc123"></div>'
        result = detector.detect_captcha(html)

        assert result.confidence > 0
        assert "CAPTCHA sitekey" in result.indicators


# =============================================================================
# Login Detection Tests
# =============================================================================

class TestLoginDetection:
    """Tests for login wall detection."""

    def test_detect_login_form(self, detector, login_html):
        """Detects login form."""
        result = detector.detect_login(login_html)

        assert result.detected is True
        assert result.condition == "login"
        assert result.confidence >= 0.5

    def test_detect_login_url(self, detector, normal_html):
        """Detects login by URL pattern."""
        result = detector.detect_login(normal_html, url="https://example.com/login")

        assert result.confidence > 0
        assert any("URL" in i for i in result.indicators)

    def test_detect_login_text(self, detector):
        """Detects login by text patterns."""
        # Multiple login indicators to reach confidence threshold
        html = '''
        <h1>Please sign in</h1>
        <p>You must be logged in to view this content</p>
        <form><input type="password"></form>
        '''
        result = detector.detect_login(html)

        assert result.detected is True
        assert any("Pattern" in i for i in result.indicators)

    def test_detect_password_field(self, detector):
        """Detects login by password field."""
        html = '<input type="password" name="password">'
        result = detector.detect_login(html)

        assert result.confidence > 0

    def test_no_login_on_normal_page(self, detector, normal_html):
        """No false positive on normal page."""
        result = detector.detect_login(normal_html)

        assert result.detected is False

    def test_login_title_detection(self, detector):
        """Detects login by page title."""
        html = '<html><head><title>Log In - Example</title></head></html>'
        result = detector.detect_login(html)

        assert result.confidence > 0


# =============================================================================
# Paywall Detection Tests
# =============================================================================

class TestPaywallDetection:
    """Tests for paywall detection."""

    def test_detect_paywall(self, detector, paywall_html):
        """Detects paywall."""
        result = detector.detect_paywall(paywall_html)

        assert result.detected is True
        assert result.condition == "paywall"
        assert result.confidence >= 0.5

    def test_detect_subscribe_text(self, detector):
        """Detects paywall by subscription text."""
        # Multiple paywall indicators to reach confidence threshold
        html = '''
        <div class="paywall">
            <p>Subscribe to continue reading this article</p>
            <p>Premium content - subscribers only</p>
        </div>
        '''
        result = detector.detect_paywall(html)

        assert result.detected is True

    def test_detect_premium_content(self, detector):
        """Detects paywall by premium content indicators."""
        html = '<div class="premium-wall">Premium content locked</div>'
        result = detector.detect_paywall(html)

        assert result.detected is True

    def test_detect_blurred_content(self, detector):
        """Detects paywall by blurred content."""
        html = '<div style="filter: blur(5px)">Content here</div>'
        result = detector.detect_paywall(html)

        assert result.confidence > 0

    def test_no_paywall_on_normal_page(self, detector, normal_html):
        """No false positive on normal page."""
        result = detector.detect_paywall(normal_html)

        assert result.detected is False


# =============================================================================
# Rate Limit Detection Tests
# =============================================================================

class TestRateLimitDetection:
    """Tests for rate limit detection."""

    def test_detect_rate_limit(self, detector, rate_limit_html):
        """Detects rate limiting."""
        result = detector.detect_rate_limit(rate_limit_html)

        assert result.detected is True
        assert result.condition == "rate_limit"

    def test_detect_429_status(self, detector, normal_html):
        """Detects rate limit by HTTP 429."""
        result = detector.detect_rate_limit(normal_html, status_code=429)

        assert result.detected is True
        assert "HTTP 429" in result.indicators

    def test_detect_rate_limit_text(self, detector):
        """Detects rate limit by text patterns."""
        html = '<p>Too many requests. Slow down!</p>'
        result = detector.detect_rate_limit(html)

        assert result.detected is True

    def test_no_rate_limit_on_normal_page(self, detector, normal_html):
        """No false positive on normal page."""
        result = detector.detect_rate_limit(normal_html)

        assert result.detected is False

    def test_detect_rate_limit_with_minutes(self, detector):
        """Detects rate limit with retry in minutes."""
        # Need 429 status code to trigger detection with minutes parsing
        html = '<p>Rate limited. Please try again in 5 minutes.</p>'
        result = detector.detect_rate_limit(html, status_code=429)

        assert result.detected is True
        # 5 minutes = 300 seconds
        assert "300" in (result.details or "")

    def test_detect_rate_limit_with_hours(self, detector):
        """Detects rate limit with retry in hours."""
        # Need 429 status code to trigger detection with hours parsing
        html = '<p>Too many requests. Please try again in 2 hours.</p>'
        result = detector.detect_rate_limit(html, status_code=429)

        assert result.detected is True
        # 2 hours = 7200 seconds
        assert "7200" in (result.details or "")


# =============================================================================
# Access Denied Detection Tests
# =============================================================================

class TestAccessDeniedDetection:
    """Tests for access denied detection."""

    def test_detect_access_denied(self, detector, access_denied_html):
        """Detects access denied."""
        result = detector.detect_access_denied(access_denied_html)

        assert result.detected is True
        assert result.condition == "access_denied"

    def test_detect_403_status(self, detector, normal_html):
        """Detects access denied by HTTP 403."""
        result = detector.detect_access_denied(normal_html, status_code=403)

        assert result.detected is True
        assert "HTTP 403" in result.indicators

    def test_detect_401_status(self, detector, normal_html):
        """Detects access denied by HTTP 401."""
        result = detector.detect_access_denied(normal_html, status_code=401)

        assert result.detected is True

    def test_detect_forbidden_text(self, detector):
        """Detects access denied by text."""
        html = '<h1>Forbidden</h1><p>You are not authorized to access this resource.</p>'
        result = detector.detect_access_denied(html)

        assert result.detected is True

    def test_no_access_denied_on_normal_page(self, detector, normal_html):
        """No false positive on normal page."""
        result = detector.detect_access_denied(normal_html)

        assert result.detected is False


# =============================================================================
# Combined Detection Tests
# =============================================================================

class TestCombinedDetection:
    """Tests for detect_all method."""

    def test_detect_all_returns_list(self, detector, normal_html):
        """detect_all returns list."""
        results = detector.detect_all(normal_html)
        assert isinstance(results, list)

    def test_detect_all_empty_on_normal(self, detector, normal_html):
        """No detections on normal page."""
        results = detector.detect_all(normal_html)
        assert len(results) == 0

    def test_detect_all_finds_captcha(self, detector, recaptcha_html):
        """detect_all finds CAPTCHA."""
        results = detector.detect_all(recaptcha_html)

        assert len(results) >= 1
        assert results[0].condition == "captcha"

    def test_detect_all_sorted_by_confidence(self, detector):
        """Results sorted by confidence (highest first)."""
        # Page with weak signals for multiple conditions
        html = """
        <p>sign in</p>
        <p>subscribe</p>
        <p>captcha</p>
        """
        results = detector.detect_all(html)

        if len(results) > 1:
            for i in range(len(results) - 1):
                assert results[i].confidence >= results[i + 1].confidence


# =============================================================================
# Exception Raising Tests
# =============================================================================

class TestDetectAndRaise:
    """Tests for detect_and_raise method."""

    def test_raises_captcha_error(self, detector, recaptcha_html):
        """Raises CaptchaError for CAPTCHA."""
        with pytest.raises(CaptchaError) as exc_info:
            detector.detect_and_raise(recaptcha_html, "https://example.com")

        assert "example.com" in str(exc_info.value)

    def test_raises_login_error(self, detector, login_html):
        """Raises LoginRequiredError for login wall."""
        with pytest.raises(LoginRequiredError):
            detector.detect_and_raise(login_html, "https://example.com/login")

    def test_raises_paywall_error(self, detector, paywall_html):
        """Raises PaywallError for paywall."""
        with pytest.raises(PaywallError):
            detector.detect_and_raise(paywall_html, "https://example.com")

    def test_raises_rate_limit_error(self, detector):
        """Raises RateLimitError for rate limit."""
        with pytest.raises(RateLimitError):
            detector.detect_and_raise("<p>too many requests</p>", status_code=429)

    def test_raises_access_denied_error(self, detector, access_denied_html):
        """Raises AccessDeniedError for access denied."""
        with pytest.raises(AccessDeniedError):
            detector.detect_and_raise(access_denied_html, status_code=403)

    def test_no_raise_on_normal(self, detector, normal_html):
        """No exception on normal page."""
        # Should not raise
        detector.detect_and_raise(normal_html, "https://example.com")


# =============================================================================
# Detection Result Tests
# =============================================================================

class TestDetectionResult:
    """Tests for DetectionResult dataclass."""

    def test_default_values(self):
        """DetectionResult has sensible defaults."""
        result = DetectionResult(detected=False)

        assert result.detected is False
        assert result.condition is None
        assert result.confidence == 0.0
        assert result.details is None
        assert result.indicators == []

    def test_with_all_fields(self):
        """DetectionResult accepts all fields."""
        result = DetectionResult(
            detected=True,
            condition="captcha",
            confidence=0.9,
            details="reCAPTCHA",
            indicators=["script found", "sitekey found"]
        )

        assert result.detected is True
        assert result.condition == "captcha"
        assert result.confidence == 0.9
        assert result.details == "reCAPTCHA"
        assert len(result.indicators) == 2


# =============================================================================
# Challenge Detection Tests
# =============================================================================

class TestChallengeDetection:
    """Tests for challenge/interstitial page detection."""

    def test_detect_ddos_guard(self, detector):
        """Detects DDoS-Guard challenge page."""
        html = """
        <html>
        <head><title>DDOS-GUARD</title></head>
        <body>
            <p>Please wait while we check your browser...</p>
        </body>
        </html>
        """
        result = detector.detect_challenge(html)

        assert result.detected is True
        assert result.condition == "challenge"
        assert "DDoS-Guard" in result.details

    def test_detect_cloudflare_challenge(self, detector):
        """Detects Cloudflare browser verification."""
        html = """
        <html>
        <body>
            <div id="cf-browser-verification">
                <p>Checking your browser before accessing</p>
            </div>
        </body>
        </html>
        """
        result = detector.detect_challenge(html)

        assert result.detected is True
        assert any("Cloudflare" in i for i in result.indicators)

    def test_detect_checking_browser(self, detector):
        """Detects 'checking your browser' text."""
        html = """
        <html>
        <body>
            <h1>Please wait</h1>
            <p>Checking your browser before accessing the website...</p>
        </body>
        </html>
        """
        result = detector.detect_challenge(html)

        assert result.detected is True
        assert any("Pattern" in i for i in result.indicators)

    def test_detect_js_redirect_timer(self, detector):
        """Detects JavaScript redirect with timer."""
        html = """
        <html>
        <head>
            <script>
                setTimeout(function() {
                    window.location.href = '/continue';
                }, 5000);
            </script>
        </head>
        <body>
            <p>Redirecting...</p>
        </body>
        </html>
        """
        result = detector.detect_challenge(html)

        assert result.detected is True
        assert any("JS redirect" in i for i in result.indicators)

    def test_detect_meta_refresh(self, detector):
        """Detects meta refresh redirect."""
        html = """
        <html>
        <head>
            <meta http-equiv="refresh" content="5;url=/continue">
        </head>
        <body>
            <p>Please wait...</p>
        </body>
        </html>
        """
        result = detector.detect_challenge(html)

        assert result.detected is True
        assert any("Meta refresh" in i for i in result.indicators)

    def test_detect_minimal_content(self, detector):
        """Detects minimal content interstitial."""
        html = """
        <html>
        <body>
            <p>Please wait</p>
        </body>
        </html>
        """
        result = detector.detect_challenge(html)

        assert any("Minimal content" in i for i in result.indicators)

    def test_no_challenge_on_normal_page(self, detector, normal_html):
        """No false positive on normal page."""
        result = detector.detect_challenge(normal_html)

        assert result.detected is False

    def test_challenge_returns_type(self, detector):
        """Challenge detection returns challenge type."""
        html = '<html><body><p>ddos-guard verification</p></body></html>'
        result = detector.detect_challenge(html)

        assert result.detected is True
        assert result.details is not None

    def test_detect_please_wait(self, detector):
        """Detects 'please wait' interstitial pages."""
        html = """
        <html>
        <body>
            <div class="loading">
                <p>Please wait while we verify your request...</p>
            </div>
        </body>
        </html>
        """
        result = detector.detect_challenge(html)

        # Should have some confidence even if not detected
        assert result.confidence > 0


# =============================================================================
# Raise For Obstacle Tests
# =============================================================================

class TestRaiseForObstacle:
    """Tests for detect_and_raise method."""

    def test_no_exception_on_normal_page(self, detector, normal_html):
        """No exception raised for normal page."""
        # Should not raise anything
        detector.detect_and_raise(normal_html, "https://example.com")

    def test_raises_captcha_error(self, detector, recaptcha_html):
        """Raises CaptchaError for CAPTCHA pages."""
        from blackreach.exceptions import CaptchaError

        with pytest.raises(CaptchaError):
            detector.detect_and_raise(recaptcha_html, "https://example.com")

    def test_raises_login_required_error(self, detector, login_html):
        """Raises LoginRequiredError for login pages."""
        from blackreach.exceptions import LoginRequiredError

        with pytest.raises(LoginRequiredError):
            detector.detect_and_raise(login_html, "https://example.com")

    def test_raises_paywall_error(self, detector, paywall_html):
        """Raises PaywallError for paywall pages."""
        from blackreach.exceptions import PaywallError

        with pytest.raises(PaywallError):
            detector.detect_and_raise(paywall_html, "https://example.com")

    def test_raises_rate_limit_error(self, detector, rate_limit_html):
        """Raises RateLimitError for rate limit pages."""
        from blackreach.exceptions import RateLimitError

        with pytest.raises(RateLimitError):
            detector.detect_and_raise(rate_limit_html, "https://example.com", status_code=429)

    def test_raises_access_denied_error(self, detector, access_denied_html):
        """Raises AccessDeniedError for access denied pages."""
        from blackreach.exceptions import AccessDeniedError

        with pytest.raises(AccessDeniedError):
            detector.detect_and_raise(access_denied_html, "https://example.com")

    def test_rate_limit_parses_retry_after(self, detector):
        """RateLimitError includes parsed retry_after."""
        from blackreach.exceptions import RateLimitError

        html = '<p>Rate limited. Please try again in 5 minutes.</p>'

        try:
            detector.detect_and_raise(html, "https://example.com", status_code=429)
            assert False, "Should have raised"
        except RateLimitError as e:
            # retry_after should be parsed from "Retry after 300s" -> 300.0
            assert e.retry_after == 300.0 or e.retry_after is None

    def test_rate_limit_invalid_retry_after_format(self, detector):
        """RateLimitError handles unparseable retry_after gracefully."""
        from blackreach.exceptions import RateLimitError
        from unittest.mock import patch, MagicMock

        # Create a mock DetectionResult with invalid retry_after format
        mock_result = MagicMock()
        mock_result.detected = True
        mock_result.condition = "rate_limit"
        mock_result.confidence = 0.9
        mock_result.indicators = []
        mock_result.details = "Retry after invalid_value"  # This will cause ValueError

        with patch.object(detector, 'detect_all', return_value=[mock_result]):
            try:
                detector.detect_and_raise("", "https://example.com")
                assert False, "Should have raised"
            except RateLimitError as e:
                # Should have handled the ValueError and set retry_after to None
                assert e.retry_after is None


# =============================================================================
# Site Characteristics Tests
# =============================================================================

class TestSiteCharacteristics:
    """Tests for site characteristics and adaptive timeout functionality."""

    def test_get_site_characteristics_wikipedia(self):
        """Wikipedia returns static site characteristics."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars = get_site_characteristics("https://en.wikipedia.org/wiki/Python")

        assert chars.site_type == SiteType.STATIC
        assert chars.network_idle_timeout <= 5000  # Should be short
        assert chars.skip_framework_detection is True
        assert chars.skip_dynamic_content_wait is True
        assert "Wikipedia" in chars.description

    def test_get_site_characteristics_github(self):
        """GitHub returns hybrid site characteristics."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars = get_site_characteristics("https://github.com/anthropics/claude-code")

        assert chars.site_type == SiteType.HYBRID
        assert chars.network_idle_timeout <= 10000
        assert chars.skip_framework_detection is True
        assert "GitHub" in chars.description

    def test_get_site_characteristics_google(self):
        """Google returns search engine characteristics."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars = get_site_characteristics("https://www.google.com/search?q=test")

        assert chars.site_type == SiteType.SEARCH_ENGINE
        assert chars.skip_framework_detection is True
        assert "Google" in chars.description

    def test_get_site_characteristics_unknown_site(self):
        """Unknown sites return default characteristics."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars = get_site_characteristics("https://some-random-spa-site.com/app")

        assert chars.site_type == SiteType.UNKNOWN
        assert chars.network_idle_timeout == 10000  # Default
        assert chars.skip_framework_detection is False

    def test_get_site_characteristics_invalid_url(self):
        """Invalid URLs return default characteristics."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars = get_site_characteristics("not-a-valid-url")

        assert chars.site_type == SiteType.UNKNOWN

    def test_get_site_characteristics_duckduckgo(self):
        """DuckDuckGo returns search engine characteristics."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars = get_site_characteristics("https://duckduckgo.com/?q=python")

        assert chars.site_type == SiteType.SEARCH_ENGINE
        assert "DuckDuckGo" in chars.description

    def test_get_site_characteristics_stackoverflow(self):
        """Stack Overflow returns static site characteristics."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars = get_site_characteristics("https://stackoverflow.com/questions/12345")

        assert chars.site_type == SiteType.STATIC
        assert chars.network_idle_timeout <= 8000
        assert "Stack Overflow" in chars.description

    def test_get_site_characteristics_arxiv(self):
        """arXiv returns static site characteristics."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars = get_site_characteristics("https://arxiv.org/abs/2301.12345")

        assert chars.site_type == SiteType.STATIC
        assert chars.skip_dynamic_content_wait is True
        assert "arXiv" in chars.description

    def test_site_type_enum_values(self):
        """SiteType enum has expected values."""
        from blackreach.detection import SiteType

        assert SiteType.STATIC.value == "static"
        assert SiteType.SPA.value == "spa"
        assert SiteType.HYBRID.value == "hybrid"
        assert SiteType.SEARCH_ENGINE.value == "search"
        assert SiteType.UNKNOWN.value == "unknown"

    def test_site_characteristics_has_all_fields(self):
        """SiteCharacteristics has all expected fields."""
        from blackreach.detection import get_site_characteristics

        chars = get_site_characteristics("https://en.wikipedia.org/wiki/Test")

        # All fields should be set
        assert hasattr(chars, 'site_type')
        assert hasattr(chars, 'network_idle_timeout')
        assert hasattr(chars, 'content_wait_timeout')
        assert hasattr(chars, 'skip_framework_detection')
        assert hasattr(chars, 'skip_dynamic_content_wait')
        assert hasattr(chars, 'min_links_for_ready')
        assert hasattr(chars, 'min_text_length_for_ready')
        assert hasattr(chars, 'description')

    def test_get_site_characteristics_case_insensitive(self):
        """URL domain matching is case-insensitive."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars_lower = get_site_characteristics("https://en.wikipedia.org/wiki/Test")
        chars_upper = get_site_characteristics("https://EN.WIKIPEDIA.ORG/wiki/Test")

        # Both should match Wikipedia
        assert chars_lower.site_type == SiteType.STATIC
        assert chars_upper.site_type == SiteType.STATIC

    def test_get_site_characteristics_libgen(self):
        """LibGen sites return static characteristics."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars = get_site_characteristics("https://libgen.rs/book/123456")

        assert chars.site_type == SiteType.STATIC
        assert chars.skip_dynamic_content_wait is True

    def test_get_site_characteristics_readthedocs(self):
        """ReadTheDocs sites return static characteristics."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars = get_site_characteristics("https://docs.myproject.readthedocs.io/en/latest/")

        assert chars.site_type == SiteType.STATIC
        assert chars.skip_dynamic_content_wait is True

    def test_get_site_characteristics_huggingface(self):
        """Hugging Face returns hybrid characteristics."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars = get_site_characteristics("https://huggingface.co/models")

        assert chars.site_type == SiteType.HYBRID

    def test_get_site_characteristics_google_scholar(self):
        """Google Scholar returns search engine characteristics."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars = get_site_characteristics("https://scholar.google.com/scholar?q=test")

        assert chars.site_type == SiteType.SEARCH_ENGINE

    def test_get_site_characteristics_pubmed(self):
        """PubMed returns static characteristics."""
        from blackreach.detection import get_site_characteristics, SiteType

        chars = get_site_characteristics("https://pubmed.ncbi.nlm.nih.gov/12345678/")

        assert chars.site_type == SiteType.STATIC
        assert chars.skip_dynamic_content_wait is True
