"""
Deep coverage tests for notifications/templates.py.

Targets uncovered paths:
- _get_jinja_env: template dir missing, Environment init exception
- format: Jinja2 render exception fallback, RATE_LIMIT_WARNING (no template file)
- get_required_context: meta parsing, loader=None branch, exception branch
"""

from unittest.mock import patch, MagicMock


class TestGetJinjaEnvMissingTemplateDir:
    """Cover _get_jinja_env when template directory doesn't exist."""

    def test_returns_none_when_template_dir_missing(self):
        from local_deep_research.notifications.templates import (
            NotificationTemplate,
        )
        from pathlib import Path

        NotificationTemplate._jinja_env = None

        # Patch os.path operations at the Path level
        original_exists = Path.exists

        def fake_exists(self):
            if str(self).endswith("templates"):
                return False
            return original_exists(self)

        try:
            with patch.object(Path, "exists", fake_exists):
                result = NotificationTemplate._get_jinja_env()
                assert result is None
        finally:
            NotificationTemplate._jinja_env = None


class TestGetJinjaEnvInitException:
    """Cover _get_jinja_env when Environment() raises."""

    def test_returns_none_on_environment_init_error(self):
        from local_deep_research.notifications.templates import (
            NotificationTemplate,
        )

        NotificationTemplate._jinja_env = None

        with patch(
            "local_deep_research.notifications.templates.Environment",
            side_effect=Exception("Jinja2 init failed"),
        ):
            result = NotificationTemplate._get_jinja_env()
            assert result is None

        # Cleanup
        NotificationTemplate._jinja_env = None


class TestFormatJinja2RenderException:
    """Cover format() when Jinja2 template rendering raises."""

    def test_falls_back_when_jinja2_render_fails(self):
        from local_deep_research.notifications.templates import (
            NotificationTemplate,
            EventType,
        )

        NotificationTemplate._jinja_env = None

        mock_env = MagicMock()
        mock_template = MagicMock()
        mock_template.render.side_effect = Exception("render failed")
        mock_env.get_template.return_value = mock_template

        with patch.object(
            NotificationTemplate, "_get_jinja_env", return_value=mock_env
        ):
            result = NotificationTemplate.format(
                EventType.RESEARCH_COMPLETED, {"query": "test"}
            )

        # Should fall back to _get_fallback_template
        assert "title" in result
        assert "body" in result
        assert "Research Completed" in result["title"]

        NotificationTemplate._jinja_env = None


class TestFormatNoTemplateFile:
    """Cover format() when event_type not in TEMPLATE_FILES."""

    def test_returns_generic_notification_for_unmapped_event(self):
        from local_deep_research.notifications.templates import (
            NotificationTemplate,
            EventType,
        )

        # RATE_LIMIT_WARNING is not in TEMPLATE_FILES
        result = NotificationTemplate.format(
            EventType.RATE_LIMIT_WARNING, {"detail": "too many requests"}
        )

        assert "title" in result
        assert "body" in result
        assert "rate_limit_warning" in result["title"]


class TestFormatJinja2Unavailable:
    """Cover format() when _get_jinja_env returns None."""

    def test_uses_fallback_when_jinja2_unavailable(self):
        from local_deep_research.notifications.templates import (
            NotificationTemplate,
            EventType,
        )

        with patch.object(
            NotificationTemplate, "_get_jinja_env", return_value=None
        ):
            result = NotificationTemplate.format(
                EventType.RESEARCH_FAILED, {"error": "timeout"}
            )

        assert "title" in result
        assert "body" in result
        assert "Research Failed" in result["title"]
        assert "Details" in result["body"]


class TestFormatCustomTemplateSafeContext:
    """Cover safe_context conversion in custom_template branch."""

    def test_none_values_become_empty_string(self):
        from local_deep_research.notifications.templates import (
            NotificationTemplate,
            EventType,
        )

        custom_template = {
            "title": "Title: {value}",
            "body": "Body: {other}",
        }
        context = {"value": None, "other": 42}

        result = NotificationTemplate.format(
            EventType.TEST, context, custom_template=custom_template
        )

        assert result["title"] == "Title: "
        assert result["body"] == "Body: 42"


class TestGetRequiredContextMetaParsing:
    """Cover get_required_context Jinja2 meta parsing."""

    def test_extracts_variables_from_template(self):
        from local_deep_research.notifications.templates import (
            NotificationTemplate,
            EventType,
        )

        # Use a real event type that has a template
        result = NotificationTemplate.get_required_context(
            EventType.RESEARCH_COMPLETED
        )

        # Should return a list (possibly empty if template dir missing)
        assert isinstance(result, list)

    def test_returns_empty_when_jinja_env_none(self):
        from local_deep_research.notifications.templates import (
            NotificationTemplate,
            EventType,
        )

        with patch.object(
            NotificationTemplate, "_get_jinja_env", return_value=None
        ):
            result = NotificationTemplate.get_required_context(EventType.TEST)
            assert result == []

    def test_returns_empty_on_template_parse_exception(self):
        from local_deep_research.notifications.templates import (
            NotificationTemplate,
            EventType,
        )

        mock_env = MagicMock()
        mock_env.get_template.side_effect = Exception("template parse error")

        with patch.object(
            NotificationTemplate, "_get_jinja_env", return_value=mock_env
        ):
            result = NotificationTemplate.get_required_context(
                EventType.RESEARCH_COMPLETED
            )
            assert result == []

    def test_meta_parsing_with_loader_none(self):
        """Cover the branch where template.environment.loader is None."""
        from local_deep_research.notifications.templates import (
            NotificationTemplate,
            EventType,
        )

        mock_env = MagicMock()
        mock_template = MagicMock()
        mock_template.environment.loader = None
        mock_env.get_template.return_value = mock_template

        with patch.object(
            NotificationTemplate, "_get_jinja_env", return_value=mock_env
        ):
            result = NotificationTemplate.get_required_context(
                EventType.RESEARCH_COMPLETED
            )
            assert isinstance(result, list)
