"""Tests for web tools input validation."""

import pytest
from pydantic import ValidationError

from crustdata_mcp.tools.web import WebFetchInput, WebSearchInput


class TestWebSearchInputValidation:
    """Tests for WebSearchInput validation."""

    def test_query_max_length(self):
        """Test query max length constraint."""
        # Valid query
        valid_query = "a" * 1000
        input_data = WebSearchInput(query=valid_query)
        assert input_data.query == valid_query

        # Invalid query - too long
        with pytest.raises(ValidationError) as exc_info:
            WebSearchInput(query="a" * 1001)
        assert "String should have at most 1000 characters" in str(exc_info.value)

    def test_geolocation_validation(self):
        """Test geolocation ISO 3166-1 alpha-2 validation."""
        # Valid geolocations
        valid_geolocations = ["US", "GB", "CA", "DE", "FR", "JP", "AU", "IN", "BR", "MX"]
        for geo in valid_geolocations:
            input_data = WebSearchInput(query="test", geolocation=geo)
            assert input_data.geolocation == geo

        # Invalid geolocations
        invalid_geolocations = [
            "us",  # lowercase
            "USA",  # too long
            "U",  # too short
            "U1",  # contains digit
            "U-",  # contains special char
        ]
        for geo in invalid_geolocations:
            with pytest.raises(ValidationError) as exc_info:
                WebSearchInput(query="test", geolocation=geo)
            assert "ISO 3166-1 alpha-2" in str(exc_info.value)

    def test_sources_validation(self):
        """Test sources enum validation."""
        # Valid sources
        valid_sources = [
            ["news"],
            ["web"],
            ["scholar-articles"],
            ["scholar-articles-enriched"],
            ["scholar-author"],
            ["ai"],
            ["social"],
            ["news", "web", "ai"],  # multiple valid sources
        ]
        for sources in valid_sources:
            input_data = WebSearchInput(query="test", sources=sources)
            assert input_data.sources == sources

        # Invalid sources
        with pytest.raises(ValidationError) as exc_info:
            WebSearchInput(query="test", sources=["invalid-source"])
        assert "Invalid source" in str(exc_info.value)

        with pytest.raises(ValidationError) as exc_info:
            WebSearchInput(query="test", sources=["news", "invalid-source", "web"])
        assert "Invalid source" in str(exc_info.value)

    def test_date_range_validation(self):
        """Test start_date < end_date validation."""
        # Valid date range
        input_data = WebSearchInput(query="test", start_date=1000000000, end_date=1000000001)
        assert input_data.start_date == 1000000000
        assert input_data.end_date == 1000000001

        # Invalid - start_date >= end_date
        with pytest.raises(ValidationError) as exc_info:
            WebSearchInput(query="test", start_date=1000000001, end_date=1000000000)
        assert "start_date" in str(exc_info.value)
        assert "must be less than" in str(exc_info.value)

        # Invalid - equal dates
        with pytest.raises(ValidationError) as exc_info:
            WebSearchInput(query="test", start_date=1000000000, end_date=1000000000)
        assert "start_date" in str(exc_info.value)
        assert "must be less than" in str(exc_info.value)

        # Valid - only start_date
        input_data = WebSearchInput(query="test", start_date=1000000000)
        assert input_data.start_date == 1000000000

        # Valid - only end_date
        input_data = WebSearchInput(query="test", end_date=1000000000)
        assert input_data.end_date == 1000000000

    def test_limit_constraints(self):
        """Test limit field constraints."""
        # Valid limits
        for limit in [1, 10, 25, 50]:
            input_data = WebSearchInput(query="test", limit=limit)
            assert input_data.limit == limit

        # Invalid - below minimum
        with pytest.raises(ValidationError) as exc_info:
            WebSearchInput(query="test", limit=0)
        assert "greater than or equal to 1" in str(exc_info.value)

        # Invalid - above maximum
        with pytest.raises(ValidationError) as exc_info:
            WebSearchInput(query="test", limit=51)
        assert "less than or equal to 50" in str(exc_info.value)

    def test_complete_valid_input(self):
        """Test complete valid input with all fields."""
        input_data = WebSearchInput(
            query="AI companies",
            limit=20,
            geolocation="US",
            sources=["news", "web"],
            site="techcrunch.com",
            start_date=1600000000,
            end_date=1700000000,
            fetch_content=True,
        )
        assert input_data.query == "AI companies"
        assert input_data.limit == 20
        assert input_data.geolocation == "US"
        assert input_data.sources == ["news", "web"]
        assert input_data.site == "techcrunch.com"
        assert input_data.start_date == 1600000000
        assert input_data.end_date == 1700000000
        assert input_data.fetch_content is True


class TestWebFetchInputValidation:
    """Tests for WebFetchInput validation."""

    def test_urls_max_length(self):
        """Test URLs array max length constraint."""
        # Valid - single URL
        input_data = WebFetchInput(urls=["https://example.com"])
        assert len(input_data.urls) == 1

        # Valid - 10 URLs (max)
        urls = [f"https://example{i}.com" for i in range(10)]
        input_data = WebFetchInput(urls=urls)
        assert len(input_data.urls) == 10

        # Invalid - more than 10 URLs
        urls = [f"https://example{i}.com" for i in range(11)]
        with pytest.raises(ValidationError) as exc_info:
            WebFetchInput(urls=urls)
        assert "at most 10" in str(exc_info.value)

    def test_url_protocol_validation(self):
        """Test URL protocol validation (http:// or https://)."""
        # Valid URLs with https://
        valid_https_urls = [
            "https://example.com",
            "https://www.example.com",
            "https://example.com/path",
            "https://example.com:8080/path?query=value",
        ]
        for url in valid_https_urls:
            input_data = WebFetchInput(urls=[url])
            assert input_data.urls[0] == url

        # Valid URLs with http://
        valid_http_urls = [
            "http://example.com",
            "http://www.example.com",
            "http://example.com/path",
        ]
        for url in valid_http_urls:
            input_data = WebFetchInput(urls=[url])
            assert input_data.urls[0] == url

        # Invalid URLs without protocol
        invalid_urls = [
            "example.com",
            "www.example.com",
            "ftp://example.com",
            "//example.com",
            "example.com/path",
        ]
        for url in invalid_urls:
            with pytest.raises(ValidationError) as exc_info:
                WebFetchInput(urls=[url])
            assert "must start with http:// or https://" in str(exc_info.value)

    def test_mixed_urls_validation(self):
        """Test validation with multiple URLs including valid and invalid."""
        # All valid
        urls = ["https://example1.com", "http://example2.com", "https://example3.com"]
        input_data = WebFetchInput(urls=urls)
        assert len(input_data.urls) == 3

        # One invalid URL should fail entire validation
        urls = ["https://example1.com", "invalid-url", "https://example3.com"]
        with pytest.raises(ValidationError) as exc_info:
            WebFetchInput(urls=urls)
        assert "must start with http:// or https://" in str(exc_info.value)

    def test_extract_text_default(self):
        """Test extract_text default value."""
        input_data = WebFetchInput(urls=["https://example.com"])
        assert input_data.extract_text is True

    def test_complete_valid_input(self):
        """Test complete valid input with all fields."""
        urls = [
            "https://example1.com",
            "https://example2.com/path",
            "http://example3.com:8080",
        ]
        input_data = WebFetchInput(urls=urls, extract_text=False)
        assert input_data.urls == urls
        assert input_data.extract_text is False
