"""
Tests for web/auth/queue_middleware.py

Tests cover:
- process_pending_queue_operations() function
- Queue processing behavior
- Error handling
"""

from unittest.mock import MagicMock, patch

from flask import Flask


class TestProcessPendingQueueOperations:
    """Tests for process_pending_queue_operations function."""

    def test_returns_early_when_no_current_user(self):
        """Should return early when g.current_user is not set."""
        app = Flask(__name__)
        app.secret_key = "test"

        from local_deep_research.web.auth.queue_middleware import (
            process_pending_queue_operations,
        )

        with app.test_request_context("/dashboard"):
            result = process_pending_queue_operations()
            assert result is None

    def test_returns_early_when_current_user_is_none(self):
        """Should return early when g.current_user is None."""
        app = Flask(__name__)
        app.secret_key = "test"

        from local_deep_research.web.auth.queue_middleware import (
            process_pending_queue_operations,
        )
        from flask import g

        with app.test_request_context("/dashboard"):
            g.current_user = None
            result = process_pending_queue_operations()
            assert result is None

    def test_extracts_username_from_string_current_user(self):
        """Should handle g.current_user as string."""
        app = Flask(__name__)
        app.secret_key = "test"

        mock_db_session = MagicMock()
        mock_queue_processor = MagicMock()
        mock_queue_processor.process_pending_operations_for_user.return_value = 0

        with (
            patch(
                "local_deep_research.web.auth.queue_middleware.db_manager"
            ) as mock_db_manager,
            patch(
                "local_deep_research.web.auth.queue_middleware.get_user_db_session"
            ) as mock_get_session,
            patch(
                "local_deep_research.web.auth.queue_middleware.queue_processor",
                mock_queue_processor,
            ),
        ):
            mock_db_manager.is_user_connected.return_value = True
            mock_get_session.return_value.__enter__ = MagicMock(
                return_value=mock_db_session
            )
            mock_get_session.return_value.__exit__ = MagicMock(
                return_value=False
            )

            from local_deep_research.web.auth.queue_middleware import (
                process_pending_queue_operations,
            )
            from flask import g

            with app.test_request_context("/dashboard"):
                g.current_user = "testuser"

                process_pending_queue_operations()

                mock_queue_processor.process_pending_operations_for_user.assert_called_once_with(
                    "testuser", mock_db_session
                )

    def test_extracts_username_from_object_current_user(self):
        """Should handle g.current_user as object with username attribute."""
        app = Flask(__name__)
        app.secret_key = "test"

        mock_user = MagicMock()
        mock_user.username = "testuser"

        mock_db_session = MagicMock()
        mock_queue_processor = MagicMock()
        mock_queue_processor.process_pending_operations_for_user.return_value = 0

        with (
            patch(
                "local_deep_research.web.auth.queue_middleware.db_manager"
            ) as mock_db_manager,
            patch(
                "local_deep_research.web.auth.queue_middleware.get_user_db_session"
            ) as mock_get_session,
            patch(
                "local_deep_research.web.auth.queue_middleware.queue_processor",
                mock_queue_processor,
            ),
        ):
            mock_db_manager.is_user_connected.return_value = True
            mock_get_session.return_value.__enter__ = MagicMock(
                return_value=mock_db_session
            )
            mock_get_session.return_value.__exit__ = MagicMock(
                return_value=False
            )

            from local_deep_research.web.auth.queue_middleware import (
                process_pending_queue_operations,
            )
            from flask import g

            with app.test_request_context("/dashboard"):
                g.current_user = mock_user

                process_pending_queue_operations()

                mock_queue_processor.process_pending_operations_for_user.assert_called_once_with(
                    "testuser", mock_db_session
                )

    def test_returns_early_when_user_not_in_connections(self):
        """Should return early when user has no open database connection."""
        app = Flask(__name__)
        app.secret_key = "test"

        mock_queue_processor = MagicMock()

        with (
            patch(
                "local_deep_research.web.auth.queue_middleware.db_manager"
            ) as mock_db_manager,
            patch(
                "local_deep_research.web.auth.queue_middleware.queue_processor",
                mock_queue_processor,
            ),
        ):
            mock_db_manager.is_user_connected.return_value = False

            from local_deep_research.web.auth.queue_middleware import (
                process_pending_queue_operations,
            )
            from flask import g

            with app.test_request_context("/dashboard"):
                g.current_user = "testuser"

                process_pending_queue_operations()

                mock_queue_processor.process_pending_operations_for_user.assert_not_called()

    def test_returns_early_when_no_db_session(self):
        """Should return early when session context returns None."""
        app = Flask(__name__)
        app.secret_key = "test"

        mock_queue_processor = MagicMock()

        with (
            patch(
                "local_deep_research.web.auth.queue_middleware.db_manager"
            ) as mock_db_manager,
            patch(
                "local_deep_research.web.auth.queue_middleware.get_user_db_session"
            ) as mock_get_session,
            patch(
                "local_deep_research.web.auth.queue_middleware.queue_processor",
                mock_queue_processor,
            ),
        ):
            mock_db_manager.is_user_connected.return_value = True
            mock_get_session.return_value.__enter__ = MagicMock(
                return_value=None
            )
            mock_get_session.return_value.__exit__ = MagicMock(
                return_value=False
            )

            from local_deep_research.web.auth.queue_middleware import (
                process_pending_queue_operations,
            )
            from flask import g

            with app.test_request_context("/dashboard"):
                g.current_user = "testuser"

                process_pending_queue_operations()

                mock_queue_processor.process_pending_operations_for_user.assert_not_called()

    def test_processes_pending_operations(self):
        """Should process pending operations for user."""
        app = Flask(__name__)
        app.secret_key = "test"

        mock_db_session = MagicMock()
        mock_queue_processor = MagicMock()
        mock_queue_processor.process_pending_operations_for_user.return_value = 3

        with (
            patch(
                "local_deep_research.web.auth.queue_middleware.db_manager"
            ) as mock_db_manager,
            patch(
                "local_deep_research.web.auth.queue_middleware.get_user_db_session"
            ) as mock_get_session,
            patch(
                "local_deep_research.web.auth.queue_middleware.queue_processor",
                mock_queue_processor,
            ),
        ):
            mock_db_manager.is_user_connected.return_value = True
            mock_get_session.return_value.__enter__ = MagicMock(
                return_value=mock_db_session
            )
            mock_get_session.return_value.__exit__ = MagicMock(
                return_value=False
            )

            from local_deep_research.web.auth.queue_middleware import (
                process_pending_queue_operations,
            )
            from flask import g

            with app.test_request_context("/dashboard"):
                g.current_user = "testuser"

                process_pending_queue_operations()

                mock_queue_processor.process_pending_operations_for_user.assert_called_once()

    def test_handles_exception_gracefully(self):
        """Should handle exceptions gracefully."""
        app = Flask(__name__)
        app.secret_key = "test"

        mock_queue_processor = MagicMock()
        mock_queue_processor.process_pending_operations_for_user.side_effect = (
            Exception("Queue error")
        )

        with (
            patch(
                "local_deep_research.web.auth.queue_middleware.db_manager"
            ) as mock_db_manager,
            patch(
                "local_deep_research.web.auth.queue_middleware.get_user_db_session"
            ) as mock_get_session,
            patch(
                "local_deep_research.web.auth.queue_middleware.queue_processor",
                mock_queue_processor,
            ),
        ):
            mock_db_manager.is_user_connected.return_value = True
            mock_db_session = MagicMock()
            mock_get_session.return_value.__enter__ = MagicMock(
                return_value=mock_db_session
            )
            mock_get_session.return_value.__exit__ = MagicMock(
                return_value=False
            )

            from local_deep_research.web.auth.queue_middleware import (
                process_pending_queue_operations,
            )
            from flask import g

            with app.test_request_context("/dashboard"):
                g.current_user = "testuser"

                # Should not raise exception
                process_pending_queue_operations()

    def test_logs_when_operations_started(self):
        """Should log when operations are started."""
        app = Flask(__name__)
        app.secret_key = "test"

        mock_db_session = MagicMock()
        mock_queue_processor = MagicMock()
        mock_queue_processor.process_pending_operations_for_user.return_value = 5

        with (
            patch(
                "local_deep_research.web.auth.queue_middleware.db_manager"
            ) as mock_db_manager,
            patch(
                "local_deep_research.web.auth.queue_middleware.get_user_db_session"
            ) as mock_get_session,
            patch(
                "local_deep_research.web.auth.queue_middleware.queue_processor",
                mock_queue_processor,
            ),
            patch(
                "local_deep_research.web.auth.queue_middleware.logger"
            ) as mock_logger,
        ):
            mock_db_manager.is_user_connected.return_value = True
            mock_get_session.return_value.__enter__ = MagicMock(
                return_value=mock_db_session
            )
            mock_get_session.return_value.__exit__ = MagicMock(
                return_value=False
            )

            from local_deep_research.web.auth.queue_middleware import (
                process_pending_queue_operations,
            )
            from flask import g

            with app.test_request_context("/dashboard"):
                g.current_user = "testuser"

                process_pending_queue_operations()

                mock_logger.info.assert_called()

    def test_does_not_log_when_zero_operations(self):
        """Should not log when no operations are started."""
        app = Flask(__name__)
        app.secret_key = "test"

        mock_db_session = MagicMock()
        mock_queue_processor = MagicMock()
        mock_queue_processor.process_pending_operations_for_user.return_value = 0

        with (
            patch(
                "local_deep_research.web.auth.queue_middleware.db_manager"
            ) as mock_db_manager,
            patch(
                "local_deep_research.web.auth.queue_middleware.get_user_db_session"
            ) as mock_get_session,
            patch(
                "local_deep_research.web.auth.queue_middleware.queue_processor",
                mock_queue_processor,
            ),
            patch(
                "local_deep_research.web.auth.queue_middleware.logger"
            ) as mock_logger,
        ):
            mock_db_manager.is_user_connected.return_value = True
            mock_get_session.return_value.__enter__ = MagicMock(
                return_value=mock_db_session
            )
            mock_get_session.return_value.__exit__ = MagicMock(
                return_value=False
            )

            from local_deep_research.web.auth.queue_middleware import (
                process_pending_queue_operations,
            )
            from flask import g

            with app.test_request_context("/dashboard"):
                g.current_user = "testuser"

                process_pending_queue_operations()

                mock_logger.info.assert_not_called()

    def test_rollback_g_db_session_on_exception(self):
        """Should rollback g.db_session when processing raises to prevent PendingRollbackError."""
        app = Flask(__name__)
        app.secret_key = "test"

        mock_queue_processor = MagicMock()
        mock_queue_processor.process_pending_operations_for_user.side_effect = (
            Exception("Queue error")
        )

        with (
            patch(
                "local_deep_research.web.auth.queue_middleware.db_manager"
            ) as mock_db_manager,
            patch(
                "local_deep_research.web.auth.queue_middleware.get_user_db_session"
            ) as mock_get_session,
            patch(
                "local_deep_research.web.auth.queue_middleware.queue_processor",
                mock_queue_processor,
            ),
        ):
            mock_db_manager.is_user_connected.return_value = True
            mock_db_session = MagicMock()
            mock_get_session.return_value.__enter__ = MagicMock(
                return_value=mock_db_session
            )
            mock_get_session.return_value.__exit__ = MagicMock(
                return_value=False
            )

            from local_deep_research.web.auth.queue_middleware import (
                process_pending_queue_operations,
            )
            from flask import g

            mock_g_session = MagicMock()

            with app.test_request_context("/dashboard"):
                g.current_user = "testuser"
                g.db_session = mock_g_session

                process_pending_queue_operations()

                mock_g_session.rollback.assert_called_once()
