"""
Tests for webhook URL validation.
Story 3.7: Webhook - Spécification URL
"""

import pytest
from unittest.mock import patch, MagicMock


class TestWebhookURLValidator:
    """Tests for WebhookURLValidator class."""

    @pytest.fixture
    def validator(self):
        """Create a WebhookURLValidator instance."""
        from middleware.validation import WebhookURLValidator
        return WebhookURLValidator()

    def test_valid_https_url(self, validator):
        """Valid HTTPS URL should pass."""
        url = "https://example.com/webhook"
        is_valid, error, details = validator.validate(url)
        assert is_valid is True
        assert error is None
        assert details is None

    def test_valid_http_url(self, validator):
        """Valid HTTP URL should pass."""
        url = "http://example.com/webhook"
        is_valid, error, details = validator.validate(url)
        assert is_valid is True
        assert error is None

    def test_invalid_scheme_ftp(self, validator):
        """FTP URL should be rejected."""
        url = "ftp://example.com/webhook"
        is_valid, error, details = validator.validate(url)
        assert is_valid is False
        assert "http" in error.lower()

    def test_invalid_scheme_no_scheme(self, validator):
        """URL without scheme should be rejected."""
        url = "example.com/webhook"
        is_valid, error, details = validator.validate(url)
        assert is_valid is False

    def test_localhost_blocked(self, validator):
        """Localhost should be blocked."""
        urls = [
            "http://localhost/webhook",
            "http://127.0.0.1/webhook",
            "http://0.0.0.0/webhook",
        ]
        for url in urls:
            is_valid, error, details = validator.validate(url)
            assert is_valid is False, f"URL {url} should be blocked"
            assert "localhost" in error.lower() or "priv" in error.lower() or "non autoris" in error.lower()

    def test_credentials_in_url_blocked(self, validator):
        """URLs with credentials should be blocked."""
        url = "https://user:password@example.com/webhook"
        is_valid, error, details = validator.validate(url)
        assert is_valid is False
        assert "credentials" in error.lower() or "identifiants" in error.lower()

    def test_empty_url_valid(self, validator):
        """Empty URL should be valid (optional parameter)."""
        is_valid, error, details = validator.validate("")
        assert is_valid is True

    def test_none_url_valid(self, validator):
        """None URL should be valid (optional parameter)."""
        is_valid, error, details = validator.validate(None)
        assert is_valid is True

    def test_url_with_port(self, validator):
        """URL with port should be valid."""
        url = "https://example.com:8080/webhook"
        is_valid, error, details = validator.validate(url)
        assert is_valid is True

    def test_url_with_query_params(self, validator):
        """URL with query parameters should be valid."""
        url = "https://example.com/webhook?token=abc123&source=api"
        is_valid, error, details = validator.validate(url)
        assert is_valid is True

    def test_url_with_path(self, validator):
        """URL with path should be valid."""
        url = "https://example.com/api/v1/notifications/translation-complete"
        is_valid, error, details = validator.validate(url)
        assert is_valid is True

    def test_url_missing_hostname(self, validator):
        """URL without hostname should be rejected."""
        url = "https:///webhook"
        is_valid, error, details = validator.validate(url)
        assert is_valid is False
        assert "hostname" in error.lower() or "hôte" in error.lower()

    def test_ipv6_localhost_blocked(self, validator):
        """IPv6 localhost should be blocked."""
        url = "http://[::1]/webhook"
        is_valid, error, details = validator.validate(url)
        assert is_valid is False

    def test_private_ip_blocked(self, validator):
        """Private IP addresses should be blocked."""
        private_ips = [
            "http://10.0.0.1/webhook",
            "http://172.16.0.1/webhook",
            "http://192.168.1.1/webhook",
        ]
        for url in private_ips:
            is_valid, error, details = validator.validate(url)
            assert is_valid is False, f"URL {url} should be blocked"
            assert "priv" in error.lower() or "non autoris" in error.lower()


class TestWebhookURLIntegration:
    """Integration tests for webhook URL in translate endpoint."""

    @pytest.fixture
    def client(self):
        """Create test client."""
        from fastapi.testclient import TestClient
        from main import app
        return TestClient(app)

    @pytest.fixture
    def auth_headers(self):
        """Create auth headers for testing."""
        # This would need a valid token in real tests
        return {"Authorization": "Bearer test_token"}

    @pytest.fixture
    def sample_file(self, tmp_path):
        """Create a sample Excel file for testing."""
        import zipfile
        file_path = tmp_path / "test.xlsx"
        # Create a minimal valid xlsx file (ZIP with correct magic bytes)
        with zipfile.ZipFile(file_path, 'w') as zf:
            zf.writestr("[Content_Types].xml", '<?xml version="1.0"?>')
        return file_path

    def test_translate_with_valid_webhook_url(self, client, sample_file):
        """Translation with valid webhook_url should succeed."""
        # This test would need proper authentication setup
        # For now, we test the validation logic directly
        from middleware.validation import webhook_validator
        
        url = "https://example.com/webhook"
        is_valid, error, details = webhook_validator.validate(url)
        assert is_valid is True

    def test_translate_with_invalid_webhook_url(self, client):
        """Translation with invalid webhook_url should return 400."""
        from middleware.validation import webhook_validator
        
        url = "ftp://example.com/webhook"
        is_valid, error, details = webhook_validator.validate(url)
        assert is_valid is False
        assert "http" in error.lower()

    def test_translate_without_webhook_url(self, client):
        """Translation without webhook_url should succeed."""
        from middleware.validation import webhook_validator
        
        # Empty webhook URL should be valid (optional)
        is_valid, error, details = webhook_validator.validate("")
        assert is_valid is True
        
        is_valid, error, details = webhook_validator.validate(None)
        assert is_valid is True


class TestWebhookValidatorSingleton:
    """Tests for the webhook_validator singleton instance."""

    def test_singleton_exists(self):
        """The webhook_validator singleton should be available."""
        from middleware.validation import webhook_validator
        assert webhook_validator is not None

    def test_singleton_is_validator(self):
        """The webhook_validator should be a WebhookURLValidator instance."""
        from middleware.validation import webhook_validator, WebhookURLValidator
        assert isinstance(webhook_validator, WebhookURLValidator)

    def test_singleton_default_settings(self):
        """The singleton should have default security settings enabled."""
        from middleware.validation import webhook_validator
        assert webhook_validator.block_private_ips is True
        assert "http" in webhook_validator.allowed_schemes
        assert "https" in webhook_validator.allowed_schemes