# tests/unit/middleware/test_storefront_gate_bypass.py
"""
Unit tests for the storefront gate bypass safety net.

Ensures that when frontend_type is None (upstream middleware failed),
storefront paths are BLOCKED rather than passed through. Non-storefront
paths with None frontend_type should pass through unchanged.
"""

from unittest.mock import AsyncMock, Mock, patch

import pytest
from fastapi import Request
from starlette.responses import JSONResponse

from middleware.storefront_access import (
    StorefrontAccessMiddleware,
    _looks_like_storefront,
)


@pytest.mark.unit
@pytest.mark.middleware
class TestLooksLikeStorefront:
    """Test the _looks_like_storefront helper."""

    def test_storefront_page_path(self):
        assert _looks_like_storefront("/storefront/products") is True

    def test_storefront_api_path(self):
        assert _looks_like_storefront("/api/v1/storefront/cart") is True

    def test_admin_path(self):
        assert _looks_like_storefront("/admin/dashboard") is False

    def test_static_path(self):
        assert _looks_like_storefront("/static/css/style.css") is False

    def test_store_path(self):
        assert _looks_like_storefront("/store/ACME/login") is False

    def test_root_path(self):
        assert _looks_like_storefront("/") is False


@pytest.mark.unit
@pytest.mark.middleware
class TestStorefrontGateBypass:
    """Test that None frontend_type can't bypass the storefront gate."""

    @pytest.mark.asyncio
    async def test_none_frontend_type_storefront_page_blocked(self):
        """frontend_type=None + /storefront/ path → blocked with HTML 403."""
        middleware = StorefrontAccessMiddleware(app=None)
        request = Mock(spec=Request)
        request.url = Mock(path="/storefront/products")
        request.state = Mock()
        request.state.frontend_type = None
        request.state.store = None
        request.state.language = "en"
        request.state.theme = None
        call_next = AsyncMock()

        with patch("app.templates_config.templates") as mock_templates:
            mock_templates.TemplateResponse.return_value = Mock(status_code=403)
            await middleware.dispatch(request, call_next)

        call_next.assert_not_called()

    @pytest.mark.asyncio
    async def test_none_frontend_type_storefront_api_blocked(self):
        """frontend_type=None + /api/v1/storefront/ path → JSON 403."""
        middleware = StorefrontAccessMiddleware(app=None)
        request = Mock(spec=Request)
        request.url = Mock(path="/api/v1/storefront/cart")
        request.state = Mock()
        request.state.frontend_type = None
        call_next = AsyncMock()

        response = await middleware.dispatch(request, call_next)

        call_next.assert_not_called()
        assert isinstance(response, JSONResponse)
        assert response.status_code == 403

    @pytest.mark.asyncio
    async def test_none_frontend_type_admin_passes_through(self):
        """frontend_type=None + /admin/ path → passes through (not storefront)."""
        middleware = StorefrontAccessMiddleware(app=None)
        request = Mock(spec=Request)
        request.url = Mock(path="/admin/dashboard")
        request.state = Mock()
        request.state.frontend_type = None
        call_next = AsyncMock(return_value=Mock())

        await middleware.dispatch(request, call_next)

        call_next.assert_called_once_with(request)

    @pytest.mark.asyncio
    async def test_none_frontend_type_static_passes_through(self):
        """frontend_type=None + /static/ path → passes through."""
        middleware = StorefrontAccessMiddleware(app=None)
        request = Mock(spec=Request)
        request.url = Mock(path="/static/css/style.css")
        request.state = Mock()
        request.state.frontend_type = None
        call_next = AsyncMock(return_value=Mock())

        await middleware.dispatch(request, call_next)

        call_next.assert_called_once_with(request)

    @pytest.mark.asyncio
    async def test_none_frontend_type_root_passes_through(self):
        """frontend_type=None + / path → passes through."""
        middleware = StorefrontAccessMiddleware(app=None)
        request = Mock(spec=Request)
        request.url = Mock(path="/")
        request.state = Mock()
        request.state.frontend_type = None
        call_next = AsyncMock(return_value=Mock())

        await middleware.dispatch(request, call_next)

        call_next.assert_called_once_with(request)
