"""
Search engine mock fixtures - Based on scottvr's patterns but updated for current codebase.

This module provides mock responses for various search engines.
"""

from typing import Any, Dict, List
from urllib.parse import urlparse

import pytest


class SearchEngineMocks:
    """Collection of search engine mock responses."""

    @staticmethod
    def wikipedia_response() -> Dict[str, Any]:
        """Mock Wikipedia API response."""
        return {
            "query": {
                "search": [
                    {
                        "title": "Artificial intelligence",
                        "snippet": "Artificial intelligence (AI) is intelligence demonstrated by machines...",
                        "pageid": 12345,
                    },
                    {
                        "title": "Machine learning",
                        "snippet": "Machine learning (ML) is a subset of artificial intelligence (AI)...",
                        "pageid": 67890,
                    },
                ]
            }
        }

    @staticmethod
    def arxiv_response() -> str:
        """Mock arXiv XML response."""
        return """<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <entry>
        <title>Test Paper Title</title>
        <id>http://arxiv.org/abs/2301.12345</id>
        <summary>This is a test paper abstract about machine learning.</summary>
        <published>2023-01-15T00:00:00Z</published>
        <author>
            <name>Test Author</name>
        </author>
    </entry>
</feed>"""

    @staticmethod
    def pubmed_search_response() -> str:
        """Mock PubMed search response."""
        return """<?xml version="1.0" encoding="UTF-8"?>
<eSearchResult>
    <IdList>
        <Id>12345678</Id>
        <Id>87654321</Id>
    </IdList>
</eSearchResult>"""

    @staticmethod
    def pubmed_article_response() -> str:
        """Mock PubMed article detail."""
        return """<?xml version="1.0" encoding="UTF-8"?>
<PubmedArticleSet>
    <PubmedArticle>
        <MedlineCitation>
            <PMID>12345678</PMID>
            <Article>
                <ArticleTitle>Test Medical Research Paper</ArticleTitle>
                <Abstract>
                    <AbstractText>This is a test medical abstract about clinical trials.</AbstractText>
                </Abstract>
                <AuthorList>
                    <Author>
                        <LastName>Smith</LastName>
                        <ForeName>John</ForeName>
                    </Author>
                </AuthorList>
            </Article>
        </MedlineCitation>
    </PubmedArticle>
</PubmedArticleSet>"""

    @staticmethod
    def semantic_scholar_response() -> Dict[str, Any]:
        """Mock Semantic Scholar API response."""
        return {
            "data": [
                {
                    "paperId": "abc123def456",  # pragma: allowlist secret
                    "title": "Deep Learning: A Comprehensive Overview",
                    "abstract": "This paper provides a comprehensive overview of deep learning techniques...",
                    "year": 2023,
                    "authors": [
                        {"authorId": "123", "name": "John Doe"},
                        {"authorId": "456", "name": "Jane Smith"},
                    ],
                    "url": "https://www.semanticscholar.org/paper/abc123def456",
                    "venue": "Journal of Machine Learning Research",
                    "citationCount": 42,
                }
            ]
        }

    @staticmethod
    def google_pse_response() -> Dict[str, Any]:
        """Mock Google Programmable Search Engine response."""
        return {
            "kind": "customsearch#search",
            "items": [
                {
                    "kind": "customsearch#result",
                    "title": "Understanding Artificial Intelligence",
                    "link": "https://example.com/ai-guide",
                    "snippet": "A comprehensive guide to understanding artificial intelligence and its applications...",
                    "displayLink": "example.com",
                    "pagemap": {
                        "metatags": [
                            {
                                "og:description": "Learn about AI, machine learning, and neural networks in this comprehensive guide."
                            }
                        ]
                    },
                },
                {
                    "kind": "customsearch#result",
                    "title": "Machine Learning Basics",
                    "link": "https://example.com/ml-basics",
                    "snippet": "Introduction to machine learning concepts and algorithms...",
                    "displayLink": "example.com",
                },
            ],
        }

    @staticmethod
    def ddg_response() -> List[Dict[str, Any]]:
        """Mock DuckDuckGo search response."""
        return [
            {
                "title": "Artificial Intelligence - Wikipedia",
                "link": "https://en.wikipedia.org/wiki/Artificial_intelligence",
                "snippet": "Artificial intelligence (AI) is intelligence demonstrated by machines...",
            },
            {
                "title": "What is AI? Artificial Intelligence Explained",
                "link": "https://example.com/what-is-ai",
                "snippet": "AI refers to the simulation of human intelligence in machines...",
            },
        ]

    @staticmethod
    def error_responses() -> Dict[str, Any]:
        """Collection of error responses for testing error handling."""
        return {
            "http_500": {"status_code": 500, "error": "Internal Server Error"},
            "http_404": {"status_code": 404, "error": "Not Found"},
            "http_429": {
                "status_code": 429,
                "error": "Too Many Requests",
                "retry_after": 60,
            },
            "http_403": {
                "status_code": 403,
                "error": "Forbidden",
                "message": "Invalid API key",
            },
            "network_timeout": {"error": "Connection timeout after 30 seconds"},
            "dns_failure": {"error": "Failed to resolve hostname"},
            "ssl_error": {"error": "SSL certificate verification failed"},
        }


def validate_wikipedia_url(url: str) -> bool:
    """
    Safely validate that a URL belongs to Wikipedia.

    This addresses the security issue mentioned in the PR review.
    """
    try:
        parsed = urlparse(url)
        hostname = parsed.hostname
        scheme = parsed.scheme

        if not hostname or not scheme:
            return False

        # Only allow HTTPS URLs for security
        if scheme not in ["http", "https"]:
            return False

        # Check for wikipedia.org domain and its subdomains
        return (
            hostname.endswith(".wikipedia.org") or hostname == "wikipedia.org"
        )
    except Exception:
        return False


@pytest.fixture
def search_engine_mocks():
    """Provide SearchEngineMocks instance as a fixture."""
    return SearchEngineMocks()


@pytest.fixture
def mock_successful_api_response(mocker):
    """Create a mock successful API response."""

    def _create_response(status_code=200, json_data=None, text_data=None):
        mock_response = mocker.Mock()
        mock_response.status_code = status_code
        mock_response.ok = status_code < 400

        if json_data is not None:
            mock_response.json.return_value = json_data
            mock_response.text = str(json_data)
        elif text_data is not None:
            mock_response.text = text_data
            mock_response.json.side_effect = ValueError("Not JSON")
        else:
            mock_response.json.return_value = {}
            mock_response.text = "{}"

        return mock_response

    return _create_response


@pytest.fixture
def mock_error_api_response(mocker):
    """Create a mock error API response."""

    def _create_error(error_type="http_500"):
        errors = SearchEngineMocks.error_responses()
        error_data = errors.get(error_type, errors["http_500"])

        if "status_code" in error_data:
            mock_response = mocker.Mock()
            mock_response.status_code = error_data["status_code"]
            mock_response.ok = False
            mock_response.text = error_data.get("error", "Error")
            mock_response.json.return_value = error_data
            return mock_response
        else:
            # Network-level error
            raise ConnectionError(error_data.get("error", "Unknown error"))

    return _create_error
