"""Test HTTP security headers."""

import pytest


class TestSecurityHeaders:
    """Test HTTP security headers are properly set."""

    @pytest.fixture
    def test_endpoint(self):
        """Return a test endpoint to check headers."""
        return "/"

    def test_x_frame_options_header(self, client, test_endpoint):
        """Test X-Frame-Options header is set correctly."""
        response = client.get(test_endpoint)
        assert "X-Frame-Options" in response.headers
        assert response.headers["X-Frame-Options"] == "SAMEORIGIN"

    def test_x_content_type_options_header(self, client, test_endpoint):
        """Test X-Content-Type-Options header is set correctly."""
        response = client.get(test_endpoint)
        assert "X-Content-Type-Options" in response.headers
        assert response.headers["X-Content-Type-Options"] == "nosniff"

    def test_referrer_policy_header(self, client, test_endpoint):
        """Test Referrer-Policy header is set correctly."""
        response = client.get(test_endpoint)
        assert "Referrer-Policy" in response.headers
        assert (
            response.headers["Referrer-Policy"]
            == "strict-origin-when-cross-origin"
        )

    def test_permissions_policy_header(self, client, test_endpoint):
        """Test Permissions-Policy header is set correctly."""
        response = client.get(test_endpoint)
        assert "Permissions-Policy" in response.headers
        permissions = response.headers["Permissions-Policy"]
        assert "geolocation=()" in permissions
        assert "microphone=()" in permissions
        assert "camera=()" in permissions

    def test_content_security_policy_header(self, client, test_endpoint):
        """Test Content-Security-Policy header is set correctly."""
        response = client.get(test_endpoint)
        assert "Content-Security-Policy" in response.headers
        csp = response.headers["Content-Security-Policy"]
        # Verify key CSP directives are present
        assert "default-src 'self'" in csp
        assert "script-src" in csp
        assert "style-src" in csp

    def test_hsts_header_not_set_for_http(self, client, test_endpoint):
        """Test HSTS header is not set for HTTP requests."""
        # In test environment, requests are HTTP by default
        response = client.get(test_endpoint)
        # HSTS should NOT be set for non-HTTPS requests
        assert "Strict-Transport-Security" not in response.headers

    def test_hsts_header_set_for_https(self, app, test_endpoint):
        """Test HSTS header is set correctly for HTTPS requests."""
        # Configure app to think we're using HTTPS
        app.config["PREFERRED_URL_SCHEME"] = "https"

        with app.test_client() as https_client:
            response = https_client.get(
                test_endpoint, environ_base={"wsgi.url_scheme": "https"}
            )
            assert "Strict-Transport-Security" in response.headers
            hsts = response.headers["Strict-Transport-Security"]
            assert "max-age=" in hsts
            assert "includeSubDomains" in hsts


class TestSecurityHeadersOnAPIEndpoints:
    """Test security headers are set on API endpoints."""

    def test_security_headers_on_api_endpoint(self, client):
        """Test security headers are present on API endpoints."""
        # Test a health check endpoint that should exist
        response = client.get("/api/health")

        # Security headers should be present even on API endpoints
        assert "X-Frame-Options" in response.headers
        assert "X-Content-Type-Options" in response.headers
        assert "Referrer-Policy" in response.headers

    def test_cors_and_security_headers_coexist(self, client):
        """Test CORS and security headers can coexist on API endpoints."""
        # API endpoints should have both CORS and security headers
        response = client.get("/api/health")

        # CORS headers (if applicable to this endpoint)
        # Note: CORS headers might only be set for certain API routes

        # Security headers should always be present
        assert "X-Frame-Options" in response.headers
        assert "X-Content-Type-Options" in response.headers


class TestSecurityHeadersComprehensive:
    """Comprehensive security header validation."""

    def test_all_critical_security_headers_present(self, client):
        """Test all critical security headers are present."""
        response = client.get("/")

        critical_headers = [
            "Content-Security-Policy",
            "X-Frame-Options",
            "X-Content-Type-Options",
            "Referrer-Policy",
            "Permissions-Policy",
        ]

        for header in critical_headers:
            assert header in response.headers, (
                f"Missing critical header: {header}"
            )

    def test_security_headers_on_authenticated_routes(self, client):
        """Test security headers are present on authenticated routes."""
        # Test auth-related endpoints
        response = client.get("/auth/login")
        assert response.status_code == 200

        assert "X-Frame-Options" in response.headers
        assert "X-Content-Type-Options" in response.headers
        assert "Content-Security-Policy" in response.headers

    def test_security_headers_values_are_secure(self, client):
        """Test security header values follow best practices."""
        response = client.get("/")

        # X-Frame-Options should be DENY or SAMEORIGIN (not ALLOW-FROM)
        xfo = response.headers.get("X-Frame-Options", "")
        assert xfo in ["DENY", "SAMEORIGIN"]

        # X-Content-Type-Options should be nosniff
        assert response.headers.get("X-Content-Type-Options") == "nosniff"

        # Referrer-Policy should not be "unsafe-url" or "no-referrer-when-downgrade"
        rp = response.headers.get("Referrer-Policy", "")
        assert rp not in ["unsafe-url", "no-referrer-when-downgrade"]
