"""
Tests for Themis context processors.
"""
from unittest.mock import MagicMock

from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser
from django.test import RequestFactory, TestCase, override_settings

from themis.context_processors import themis_settings, user_preferences

User = get_user_model()


class ThemisSettingsContextProcessorTest(TestCase):
    """Tests for the themis_settings context processor."""

    def setUp(self):
        self.factory = RequestFactory()
        self.request = self.factory.get("/")

    @override_settings(THEMIS_APP_NAME="Test App")
    def test_returns_configured_values(self):
        """Returns values from Django settings when configured."""
        context = themis_settings(self.request)
        self.assertEqual(context["themis_app_name"], "Test App")

    @override_settings()
    def test_returns_defaults_when_not_configured(self):
        """Returns sensible defaults when THEMIS_* settings are absent."""
        from django.conf import settings

        for attr in ["THEMIS_APP_NAME"]:
            if hasattr(settings, attr):
                delattr(settings, attr)

        context = themis_settings(self.request)
        self.assertEqual(context["themis_app_name"], "Application")

    def test_returns_expected_keys(self):
        """Context has all expected keys."""
        context = themis_settings(self.request)
        expected_keys = {
            "themis_app_name",
            "themis_notification_poll_interval",
        }
        self.assertEqual(set(context.keys()), expected_keys)

    def test_notification_poll_interval_default(self):
        """Notification poll interval defaults to 60 seconds."""
        context = themis_settings(self.request)
        self.assertEqual(context["themis_notification_poll_interval"], 60)

    @override_settings(THEMIS_NOTIFICATION_POLL_INTERVAL=0)
    def test_notification_poll_interval_disabled(self):
        """Notification polling can be disabled with 0."""
        context = themis_settings(self.request)
        self.assertEqual(context["themis_notification_poll_interval"], 0)


class UserPreferencesContextProcessorTest(TestCase):
    """Tests for the user_preferences context processor."""

    def setUp(self):
        self.factory = RequestFactory()

    def test_authenticated_user(self):
        """Returns user's preferences when authenticated."""
        user = User.objects.create_user(username="ctxuser", password="pass123")
        user.profile.home_timezone = "America/Toronto"
        user.profile.date_format = "DD/MM/YYYY"
        user.profile.time_format = "12-hour"
        user.profile.theme_mode = "dark"
        user.profile.theme_name = "dracula"
        user.profile.dark_theme_name = "night"
        user.profile.save()

        request = self.factory.get("/")
        request.user = user

        context = user_preferences(request)
        self.assertEqual(context["user_timezone"], "America/Toronto")
        self.assertEqual(context["user_date_format"], "DD/MM/YYYY")
        self.assertEqual(context["user_time_format"], "12-hour")
        self.assertFalse(context["user_is_traveling"])
        self.assertEqual(context["user_theme_mode"], "dark")
        self.assertEqual(context["user_theme_name"], "dracula")
        self.assertEqual(context["user_dark_theme_name"], "night")
        self.assertEqual(context["user_profile"], user.profile)

    def test_traveling_user(self):
        """Returns traveling timezone and is_traveling=True."""
        user = User.objects.create_user(username="travelctx", password="pass123")
        user.profile.home_timezone = "America/Toronto"
        user.profile.current_timezone = "Asia/Tokyo"
        user.profile.save()

        request = self.factory.get("/")
        request.user = user

        context = user_preferences(request)
        self.assertEqual(context["user_timezone"], "Asia/Tokyo")
        self.assertTrue(context["user_is_traveling"])

    def test_anonymous_user(self):
        """Returns defaults for anonymous users."""
        request = self.factory.get("/")
        request.user = AnonymousUser()

        context = user_preferences(request)
        self.assertEqual(context["user_timezone"], "UTC")
        self.assertEqual(context["user_date_format"], "YYYY-MM-DD")
        self.assertEqual(context["user_time_format"], "24-hour")
        self.assertFalse(context["user_is_traveling"])
        self.assertEqual(context["user_theme_mode"], "auto")
        self.assertEqual(context["user_theme_name"], "corporate")
        self.assertEqual(context["user_dark_theme_name"], "business")
        self.assertIsNone(context["user_profile"])

    def test_respects_theme_middleware_attrs(self):
        """Uses request.themis_* attributes if set by ThemeMiddleware."""
        user = User.objects.create_user(username="mwuser", password="pass123")
        user.profile.theme_mode = "light"
        user.profile.theme_name = "cupcake"
        user.profile.dark_theme_name = "halloween"
        user.profile.save()

        request = self.factory.get("/")
        request.user = user
        # Simulate ThemeMiddleware having set these
        request.themis_theme_mode = "light"
        request.themis_theme_name = "cupcake"
        request.themis_dark_theme_name = "halloween"

        context = user_preferences(request)
        self.assertEqual(context["user_theme_mode"], "light")
        self.assertEqual(context["user_theme_name"], "cupcake")
        self.assertEqual(context["user_dark_theme_name"], "halloween")

    def test_returns_expected_keys(self):
        """Context has all expected keys."""
        request = self.factory.get("/")
        request.user = AnonymousUser()
        context = user_preferences(request)
        expected_keys = {
            "user_timezone",
            "user_date_format",
            "user_time_format",
            "user_is_traveling",
            "user_theme_mode",
            "user_theme_name",
            "user_dark_theme_name",
            "user_profile",
        }
        self.assertEqual(set(context.keys()), expected_keys)
