# tests/unit/middleware/test_store_context_custom_subdomain.py
"""
Unit tests for StorePlatform.custom_subdomain resolution in StoreContextMiddleware.

Tests the platform-specific subdomain override that allows a single store
to have different subdomains on different platforms:
  - acme.omsflow.lu → Store.subdomain="acme" (default, works for all platforms)
  - acme-rewards.rewardflow.lu → StorePlatform.custom_subdomain="acme-rewards" on Loyalty platform
"""

from unittest.mock import MagicMock, Mock, patch

import pytest
from sqlalchemy.orm import Session

from middleware.store_context import StoreContextManager


@pytest.mark.unit
@pytest.mark.stores
class TestCustomSubdomainResolution:
    """Test StorePlatform.custom_subdomain lookup in get_store_from_context."""

    def test_custom_subdomain_found_returns_store(self):
        """When custom_subdomain matches on the platform, return the store."""
        mock_db = Mock(spec=Session)
        mock_platform = Mock()
        mock_platform.id = 2
        mock_platform.code = "loyalty"

        mock_store_platform = Mock()
        mock_store_platform.store_id = 42

        mock_store = Mock()
        mock_store.id = 42
        mock_store.is_active = True
        mock_store.name = "Acme Corp"

        # First query: StorePlatform lookup (custom_subdomain match)
        # Second query: Store lookup by id
        call_count = [0]

        def side_effect_query(model):
            result = MagicMock()
            call_count[0] += 1
            if call_count[0] == 1:
                # StorePlatform query
                result.filter.return_value.first.return_value = mock_store_platform
            else:
                # Store query
                result.filter.return_value.first.return_value = mock_store
            return result

        mock_db.query.side_effect = side_effect_query

        context = {
            "detection_method": "subdomain",
            "subdomain": "acme-rewards",
            "_platform": mock_platform,
        }

        store = StoreContextManager.get_store_from_context(mock_db, context)

        assert store is mock_store

    def test_custom_subdomain_not_found_returns_none_on_platform(self):
        """When custom_subdomain doesn't match on a platform, return None (fail-closed)."""
        mock_db = Mock(spec=Session)
        mock_platform = Mock()
        mock_platform.id = 2
        mock_platform.code = "loyalty"

        # StorePlatform query → no match
        mock_db.query.return_value.filter.return_value.first.return_value = None

        context = {
            "detection_method": "subdomain",
            "subdomain": "acme",
            "_platform": mock_platform,
        }

        store = StoreContextManager.get_store_from_context(mock_db, context)

        assert store is None

    def test_no_platform_subdomain_uses_global_store_subdomain(self):
        """When no platform context, subdomain detection uses global Store.subdomain."""
        mock_db = Mock(spec=Session)
        mock_store = Mock()
        mock_store.is_active = True
        mock_store.name = "Acme Corp"

        mock_db.query.return_value.filter.return_value.filter.return_value.first.return_value = mock_store

        context = {
            "detection_method": "subdomain",
            "subdomain": "acme",
            # No "_platform" key — dev mode
        }

        store = StoreContextManager.get_store_from_context(mock_db, context)

        assert store is mock_store

    def test_no_platform_skips_custom_subdomain_lookup(self):
        """When no platform in context, skip custom_subdomain and use Store.subdomain."""
        mock_db = Mock(spec=Session)
        mock_store = Mock()
        mock_store.is_active = True

        mock_db.query.return_value.filter.return_value.filter.return_value.first.return_value = mock_store

        context = {
            "detection_method": "subdomain",
            "subdomain": "acme",
            # No "_platform" key
        }

        store = StoreContextManager.get_store_from_context(mock_db, context)

        assert store is mock_store

    def test_path_based_detection_skips_custom_subdomain(self):
        """Path-based detection should not check custom_subdomain (only subdomain mode)."""
        mock_db = Mock(spec=Session)
        mock_platform = Mock()
        mock_platform.id = 1

        mock_store = Mock()
        mock_store.is_active = True

        mock_db.query.return_value.filter.return_value.filter.return_value.first.return_value = mock_store

        context = {
            "detection_method": "path",
            "subdomain": "acme",
            "_platform": mock_platform,
        }

        store = StoreContextManager.get_store_from_context(mock_db, context)

        assert store is mock_store

    def test_custom_subdomain_store_inactive_returns_none(self):
        """When custom_subdomain matches but the store is inactive, fall back."""
        mock_db = Mock(spec=Session)
        mock_platform = Mock()
        mock_platform.id = 2
        mock_platform.code = "loyalty"

        mock_store_platform = Mock()
        mock_store_platform.store_id = 42

        # Query sequence:
        # 1. StorePlatform → match
        # 2. Store by id → None (inactive)
        # 3. Store by subdomain → None (fallback also fails)
        call_count = [0]

        def side_effect_query(model):
            result = MagicMock()
            call_count[0] += 1
            if call_count[0] == 1:
                # StorePlatform query → match
                result.filter.return_value.first.return_value = mock_store_platform
            elif call_count[0] == 2:
                # Store by id → None (inactive, filtered out)
                result.filter.return_value.first.return_value = None
            else:
                # Store.subdomain fallback → None
                result.filter.return_value.filter.return_value.first.return_value = None
            return result

        mock_db.query.side_effect = side_effect_query

        context = {
            "detection_method": "subdomain",
            "subdomain": "acme-rewards",
            "_platform": mock_platform,
        }

        store = StoreContextManager.get_store_from_context(mock_db, context)

        assert store is None


@pytest.mark.unit
@pytest.mark.middleware
class TestPlatformInjectionIntoStoreContext:
    """Test that platform is properly injected into store_context for subdomain lookup."""

    def test_platform_injected_into_context_when_available(self):
        """StoreContextMiddleware should inject platform into store_context."""
        # This tests the dispatch method's platform injection logic
        # We verify that when request.state.platform is set, it gets added
        # to the store_context dict before get_store_from_context is called

        mock_platform = Mock()
        mock_platform.id = 1
        mock_platform.code = "oms"

        mock_request = Mock()
        mock_request.state = MagicMock()
        mock_request.state.platform = mock_platform
        mock_request.state.platform_clean_path = "/store/login"
        mock_request.headers = {"host": "acme.omsflow.lu"}
        mock_request.url = Mock(path="/store/login")

        with patch("middleware.store_context.settings") as mock_settings:
            mock_settings.main_domain = "omsflow.lu"

            context = StoreContextManager.detect_store_context(mock_request)

            assert context is not None
            assert context["detection_method"] == "subdomain"
            assert context["subdomain"] == "acme"

            # The middleware dispatch adds _platform after detect_store_context
            # Verify the context is suitable for platform injection
            context["_platform"] = mock_platform
            assert context.get("_platform") is mock_platform
