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

Tests cover:
- cleanup_stale_sessions() function
- Session recovery mechanisms
- Session clearing behavior
"""

from unittest.mock import MagicMock, patch

from flask import Flask


class TestCleanupStaleSessions:
    """Tests for cleanup_stale_sessions function."""

    def test_skips_when_should_skip_returns_true(self):
        """Should skip when should_skip_session_cleanup returns True."""
        app = Flask(__name__)
        app.secret_key = "test"

        with patch(
            "local_deep_research.web.auth.session_cleanup.should_skip_session_cleanup"
        ) as mock_skip:
            mock_skip.return_value = True

            from local_deep_research.web.auth.session_cleanup import (
                cleanup_stale_sessions,
            )

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

    def test_skips_when_no_username_in_session(self):
        """Should skip when no username in session."""
        app = Flask(__name__)
        app.secret_key = "test"

        with patch(
            "local_deep_research.web.auth.session_cleanup.should_skip_session_cleanup"
        ) as mock_skip:
            mock_skip.return_value = False

            from local_deep_research.web.auth.session_cleanup import (
                cleanup_stale_sessions,
            )

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

    def test_skips_when_user_has_db_connection(self):
        """Should skip when user has active database connection."""
        app = Flask(__name__)
        app.secret_key = "test"

        with (
            patch(
                "local_deep_research.web.auth.session_cleanup.should_skip_session_cleanup"
            ) as mock_skip,
            patch(
                "local_deep_research.web.auth.session_cleanup.db_manager"
            ) as mock_db_manager,
        ):
            mock_skip.return_value = False
            mock_db_manager.is_user_connected.return_value = True

            from local_deep_research.web.auth.session_cleanup import (
                cleanup_stale_sessions,
            )
            from flask import session

            with app.test_request_context("/dashboard"):
                session["username"] = "testuser"

                result = cleanup_stale_sessions()
                assert result is None

    def test_skips_when_user_has_temp_auth_token(self):
        """Should skip when user has temp_auth_token (recovery possible)."""
        app = Flask(__name__)
        app.secret_key = "test"

        with (
            patch(
                "local_deep_research.web.auth.session_cleanup.should_skip_session_cleanup"
            ) as mock_skip,
            patch(
                "local_deep_research.web.auth.session_cleanup.db_manager"
            ) as mock_db_manager,
        ):
            mock_skip.return_value = False
            mock_db_manager.is_user_connected.return_value = False
            mock_db_manager.has_encryption = True

            from local_deep_research.web.auth.session_cleanup import (
                cleanup_stale_sessions,
            )
            from flask import session

            with app.test_request_context("/dashboard"):
                session["username"] = "testuser"
                session["temp_auth_token"] = "some_token"

                cleanup_stale_sessions()
                # Session should not be cleared
                assert session.get("username") == "testuser"

    def test_skips_when_database_unencrypted(self):
        """Should skip when database is unencrypted (recovery possible with dummy)."""
        app = Flask(__name__)
        app.secret_key = "test"

        with (
            patch(
                "local_deep_research.web.auth.session_cleanup.should_skip_session_cleanup"
            ) as mock_skip,
            patch(
                "local_deep_research.web.auth.session_cleanup.db_manager"
            ) as mock_db_manager,
        ):
            mock_skip.return_value = False
            mock_db_manager.is_user_connected.return_value = False
            mock_db_manager.has_encryption = False

            from local_deep_research.web.auth.session_cleanup import (
                cleanup_stale_sessions,
            )
            from flask import session

            with app.test_request_context("/dashboard"):
                session["username"] = "testuser"

                cleanup_stale_sessions()
                # Session should not be cleared (unencrypted DB can use dummy password)
                assert session.get("username") == "testuser"

    def test_clears_session_when_no_recovery_mechanism(self):
        """Should clear session when no recovery mechanism available."""
        app = Flask(__name__)
        app.secret_key = "test"

        mock_session_password_store = MagicMock()
        mock_session_password_store.get_session_password.return_value = None

        with (
            patch(
                "local_deep_research.web.auth.session_cleanup.should_skip_session_cleanup"
            ) as mock_skip,
            patch(
                "local_deep_research.web.auth.session_cleanup.db_manager"
            ) as mock_db_manager,
            patch(
                "local_deep_research.database.session_passwords.session_password_store",
                mock_session_password_store,
            ),
        ):
            mock_skip.return_value = False
            mock_db_manager.is_user_connected.return_value = False
            mock_db_manager.has_encryption = True

            from local_deep_research.web.auth.session_cleanup import (
                cleanup_stale_sessions,
            )
            from flask import session

            with app.test_request_context("/dashboard"):
                session["username"] = "testuser"
                session["session_id"] = "session_123"

                cleanup_stale_sessions()

                # Session should be cleared
                assert session.get("username") is None

    def test_keeps_session_when_password_found_in_store(self):
        """Should keep session when password found in session password store."""
        app = Flask(__name__)
        app.secret_key = "test"

        mock_session_password_store = MagicMock()
        mock_session_password_store.get_session_password.return_value = (
            "stored_password"
        )

        with (
            patch(
                "local_deep_research.web.auth.session_cleanup.should_skip_session_cleanup"
            ) as mock_skip,
            patch(
                "local_deep_research.web.auth.session_cleanup.db_manager"
            ) as mock_db_manager,
            patch(
                "local_deep_research.database.session_passwords.session_password_store",
                mock_session_password_store,
            ),
        ):
            mock_skip.return_value = False
            mock_db_manager.is_user_connected.return_value = False
            mock_db_manager.has_encryption = True

            from local_deep_research.web.auth.session_cleanup import (
                cleanup_stale_sessions,
            )
            from flask import session

            with app.test_request_context("/dashboard"):
                session["username"] = "testuser"
                session["session_id"] = "session_123"

                cleanup_stale_sessions()

                # Session should not be cleared
                assert session.get("username") == "testuser"

    def test_clears_session_when_no_session_id(self):
        """Should clear session when no session_id available."""
        app = Flask(__name__)
        app.secret_key = "test"

        with (
            patch(
                "local_deep_research.web.auth.session_cleanup.should_skip_session_cleanup"
            ) as mock_skip,
            patch(
                "local_deep_research.web.auth.session_cleanup.db_manager"
            ) as mock_db_manager,
        ):
            mock_skip.return_value = False
            mock_db_manager.is_user_connected.return_value = False
            mock_db_manager.has_encryption = True

            from local_deep_research.web.auth.session_cleanup import (
                cleanup_stale_sessions,
            )
            from flask import session

            with app.test_request_context("/dashboard"):
                session["username"] = "testuser"
                # No session_id set

                cleanup_stale_sessions()

                # Session should be cleared
                assert session.get("username") is None

    def test_logs_when_clearing_session_no_connection(self):
        """Should log when clearing session due to no database connection."""
        app = Flask(__name__)
        app.secret_key = "test"

        mock_session_password_store = MagicMock()
        mock_session_password_store.get_session_password.return_value = None

        with (
            patch(
                "local_deep_research.web.auth.session_cleanup.should_skip_session_cleanup"
            ) as mock_skip,
            patch(
                "local_deep_research.web.auth.session_cleanup.db_manager"
            ) as mock_db_manager,
            patch(
                "local_deep_research.database.session_passwords.session_password_store",
                mock_session_password_store,
            ),
            patch(
                "local_deep_research.web.auth.session_cleanup.logger"
            ) as mock_logger,
        ):
            mock_skip.return_value = False
            mock_db_manager.is_user_connected.return_value = False
            mock_db_manager.has_encryption = True

            from local_deep_research.web.auth.session_cleanup import (
                cleanup_stale_sessions,
            )
            from flask import session

            with app.test_request_context("/dashboard"):
                session["username"] = "testuser"
                session["session_id"] = "session_123"

                cleanup_stale_sessions()

                mock_logger.info.assert_called()

    def test_logs_when_clearing_session_no_recovery(self):
        """Should log when clearing session due to no recovery mechanism."""
        app = Flask(__name__)
        app.secret_key = "test"

        with (
            patch(
                "local_deep_research.web.auth.session_cleanup.should_skip_session_cleanup"
            ) as mock_skip,
            patch(
                "local_deep_research.web.auth.session_cleanup.db_manager"
            ) as mock_db_manager,
            patch(
                "local_deep_research.web.auth.session_cleanup.logger"
            ) as mock_logger,
        ):
            mock_skip.return_value = False
            mock_db_manager.is_user_connected.return_value = False
            mock_db_manager.has_encryption = True

            from local_deep_research.web.auth.session_cleanup import (
                cleanup_stale_sessions,
            )
            from flask import session

            with app.test_request_context("/dashboard"):
                session["username"] = "testuser"
                # No session_id set

                cleanup_stale_sessions()

                mock_logger.info.assert_called()
