# tests/integration/middleware/test_middleware_stack.py
"""
Integration tests for the complete middleware stack.

These tests verify that all middleware components work together correctly
through real HTTP requests, ensuring proper execution order and state injection.

Note: These tests use pre-registered routes in middleware_test_routes.py.
The conftest patches get_db and settings.platform_domain for proper testing.
"""

import pytest


@pytest.mark.integration
@pytest.mark.middleware
class TestMiddlewareStackIntegration:
    """Test the full middleware stack with real HTTP requests."""

    # ========================================================================
    # Admin Context Tests
    # ========================================================================

    def test_admin_path_sets_admin_context(self, client):
        """Test that /admin/* paths set ADMIN context type."""
        response = client.get("/admin/middleware-test/context")

        assert response.status_code == 200
        data = response.json()
        assert data["context_type"] == "admin"

    def test_admin_subdomain_sets_admin_context(self, client):
        """Test that admin.* subdomain with API path sets context correctly."""
        response = client.get(
            "/api/middleware-test/admin-subdomain-context",
            headers={"host": "admin.platform.com"},
        )

        assert response.status_code == 200
        data = response.json()
        # API path takes precedence
        assert data["context_type"] == "api"

    # ========================================================================
    # API Context Tests
    # ========================================================================

    def test_api_path_sets_api_context(self, client):
        """Test that /api/* paths set API context type."""
        response = client.get("/api/middleware-test/context")

        assert response.status_code == 200
        data = response.json()
        assert data["context_type"] == "api"

    # ========================================================================
    # Shop Context Tests
    # ========================================================================
    # Note: Vendor dashboard context tests are covered by unit tests in
    # tests/unit/middleware/test_context.py since /vendor/* integration test
    # routes are shadowed by the catch-all /vendor/{vendor_code}/{slug} route.

    def test_shop_path_with_subdomain_sets_shop_context(
        self, client, vendor_with_subdomain
    ):
        """Test that /shop/* paths with vendor subdomain set SHOP context."""
        response = client.get(
            "/shop/middleware-test/context",
            headers={"host": f"{vendor_with_subdomain.subdomain}.platform.com"},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["context_type"] == "shop"
        assert data["vendor_id"] == vendor_with_subdomain.id
        assert data["has_theme"] is True

    def test_shop_path_with_custom_domain_sets_shop_context(
        self, client, vendor_with_custom_domain
    ):
        """Test that /shop/* paths with custom domain set SHOP context."""
        response = client.get(
            "/shop/middleware-test/custom-domain-context",
            headers={"host": "customdomain.com"},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["context_type"] == "shop"
        # Custom domain may or may not detect vendor depending on is_verified
        if data["vendor_id"]:
            assert data["vendor_id"] == vendor_with_custom_domain.id

    # ========================================================================
    # Middleware Execution Order Tests
    # ========================================================================

    def test_vendor_context_runs_before_context_detection(
        self, client, vendor_with_subdomain
    ):
        """Test that VendorContextMiddleware runs before ContextDetectionMiddleware."""
        response = client.get(
            "/middleware-test/middleware-order",
            headers={"host": f"{vendor_with_subdomain.subdomain}.platform.com"},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["vendor_detected"] is True
        assert data["has_clean_path"] is True
        assert data["has_context_type"] is True

    def test_theme_context_runs_after_vendor_context(self, client, vendor_with_theme):
        """Test that ThemeContextMiddleware runs after VendorContextMiddleware."""
        response = client.get(
            "/middleware-test/execution-order",
            headers={"host": f"{vendor_with_theme.subdomain}.platform.com"},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["has_vendor"] is True
        assert data["has_theme"] is True
        assert data["theme_primary_color"] == "#FF5733"

    # ========================================================================
    # Static File Handling Tests
    # ========================================================================

    def test_static_files_skip_vendor_detection(self, client):
        """Test that static file requests skip vendor detection."""
        response = client.get("/static/css/style.css")
        # We expect 404 (file doesn't exist) but middleware should have run
        assert response.status_code in [404, 200]

    # ========================================================================
    # Error Handling Tests
    # ========================================================================

    def test_missing_vendor_graceful_handling(self, client):
        """Test that missing vendor is handled gracefully."""
        response = client.get(
            "/api/middleware-test/missing-vendor",
            headers={"host": "nonexistent.platform.com"},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["has_vendor"] is False or data["vendor"] is None
        assert data["context_type"] is not None

    def test_inactive_vendor_not_loaded(self, client, middleware_inactive_vendor):
        """Test that inactive vendors are not loaded."""
        response = client.get(
            "/api/middleware-test/inactive-vendor",
            headers={"host": f"{middleware_inactive_vendor.subdomain}.platform.com"},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["has_vendor"] is False or data["vendor"] is None
