"""
Tests for Themis template tags and filters.
"""
from datetime import date, time
from unittest.mock import MagicMock

from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser
from django.template import Context, Template
from django.test import RequestFactory, TestCase

from themis.templatetags.themis_tags import (
    themis_body_attrs,
    user_date,
    user_number,
    user_time,
    user_timezone_name,
)

User = get_user_model()


class UserDateFilterTest(TestCase):
    """Tests for the user_date filter."""

    def setUp(self):
        self.user = User.objects.create_user(username="datefilter", password="pass123")
        self.user.profile.date_format = "DD/MM/YYYY"
        self.user.profile.save()

    def test_formats_date(self):
        """Formats date according to user preference."""
        result = user_date(date(2024, 12, 25), self.user)
        self.assertEqual(result, "25/12/2024")

    def test_empty_for_none(self):
        """Returns empty string for None."""
        self.assertEqual(user_date(None, self.user), "")

    def test_empty_for_falsy(self):
        """Returns empty string for falsy values."""
        self.assertEqual(user_date("", self.user), "")

    def test_in_template(self):
        """Filter works in a template context."""
        template = Template("{% load themis_tags %}{{ d|user_date:user }}")
        context = Context({"d": date(2024, 12, 25), "user": self.user})
        output = template.render(context)
        self.assertEqual(output.strip(), "25/12/2024")


class UserTimeFilterTest(TestCase):
    """Tests for the user_time filter."""

    def setUp(self):
        self.user = User.objects.create_user(username="timefilter", password="pass123")
        self.user.profile.time_format = "12-hour"
        self.user.profile.save()

    def test_formats_time(self):
        """Formats time according to user preference."""
        result = user_time(time(15, 30), self.user)
        self.assertEqual(result, "03:30 PM")

    def test_empty_for_none(self):
        """Returns empty string for None."""
        self.assertEqual(user_time(None, self.user), "")

    def test_in_template(self):
        """Filter works in a template context."""
        template = Template("{% load themis_tags %}{{ t|user_time:user }}")
        context = Context({"t": time(15, 30), "user": self.user})
        output = template.render(context)
        self.assertEqual(output.strip(), "03:30 PM")


class UserNumberFilterTest(TestCase):
    """Tests for the user_number filter."""

    def setUp(self):
        self.user = User.objects.create_user(username="numfilter", password="pass123")
        self.user.profile.thousand_separator = "period"
        self.user.profile.save()

    def test_formats_number(self):
        """Formats number according to user preference."""
        result = user_number(1000000, self.user)
        self.assertEqual(result, "1.000.000")

    def test_empty_for_none(self):
        """Returns empty string for None."""
        self.assertEqual(user_number(None, self.user), "")

    def test_in_template(self):
        """Filter works in a template context."""
        template = Template("{% load themis_tags %}{{ n|user_number:user }}")
        context = Context({"n": 50000, "user": self.user})
        output = template.render(context)
        self.assertEqual(output.strip(), "50.000")


class UserTimezoneNameTagTest(TestCase):
    """Tests for the user_timezone_name tag."""

    def test_returns_user_timezone(self):
        """Returns user's effective timezone."""
        user = User.objects.create_user(username="tztag", password="pass123")
        user.profile.home_timezone = "Europe/Berlin"
        user.profile.save()
        self.assertEqual(user_timezone_name(user), "Europe/Berlin")

    def test_returns_utc_for_no_profile(self):
        """Returns UTC for user without profile."""
        user_no_profile = MagicMock(spec=[])
        self.assertEqual(user_timezone_name(user_no_profile), "UTC")

    def test_in_template(self):
        """Tag works in a template context."""
        user = User.objects.create_user(username="tztag2", password="pass123")
        user.profile.home_timezone = "Asia/Tokyo"
        user.profile.save()
        template = Template("{% load themis_tags %}{% user_timezone_name user %}")
        context = Context({"user": user})
        output = template.render(context)
        self.assertEqual(output.strip(), "Asia/Tokyo")


class ThemisBodyAttrsTagTest(TestCase):
    """Tests for the themis_body_attrs tag."""

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

    def test_authenticated_user(self):
        """Returns user's date/time/week-start format as data attributes."""
        user = User.objects.create_user(username="bodyattrs", password="pass123")
        user.profile.date_format = "DD/MM/YYYY"
        user.profile.time_format = "12-hour"
        user.profile.week_start = "sunday"
        user.profile.save()

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

        context = Context({"request": request})
        result = themis_body_attrs(context)
        self.assertIn('data-user-date-format="DD/MM/YYYY"', result)
        self.assertIn('data-user-time-format="12-hour"', result)
        self.assertIn('data-user-week-start="sunday"', result)

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

        context = Context({"request": request})
        result = themis_body_attrs(context)
        self.assertIn('data-user-date-format="YYYY-MM-DD"', result)
        self.assertIn('data-user-time-format="24-hour"', result)
        self.assertIn('data-user-week-start="monday"', result)

    def test_no_request(self):
        """Returns defaults when no request in context."""
        context = Context({})
        result = themis_body_attrs(context)
        self.assertIn('data-user-date-format="YYYY-MM-DD"', result)
        self.assertIn('data-user-time-format="24-hour"', result)
        self.assertIn('data-user-week-start="monday"', result)

    def test_in_template(self):
        """Tag works in a template context."""
        user = User.objects.create_user(username="bodyattrs2", password="pass123")
        user.profile.date_format = "DD.MM.YYYY"
        user.profile.time_format = "24-hour"
        user.profile.week_start = "saturday"
        user.profile.save()

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

        template = Template('{% load themis_tags %}<body {% themis_body_attrs %}>')
        context = Context({"request": request})
        output = template.render(context)
        self.assertIn('data-user-date-format="DD.MM.YYYY"', output)
        self.assertIn('data-user-time-format="24-hour"', output)
        self.assertIn('data-user-week-start="saturday"', output)
