"""
Tests for database_init.py engine disposal.

These tests verify that SQLAlchemy engines are properly disposed in the
database initialization module to prevent file descriptor leaks.
"""

from unittest.mock import MagicMock, patch


class TestInitDatabaseEngineDisposal:
    """Tests for engine disposal in init_database()."""

    @patch(
        "local_deep_research.library.download_management.database_init.create_engine"
    )
    @patch("local_deep_research.library.download_management.database_init.Base")
    def test_init_database_disposes_engine_on_success(
        self, mock_base, mock_create_engine
    ):
        """Test that init_database() disposes engine even on success."""
        from local_deep_research.library.download_management.database_init import (
            init_database,
        )

        mock_engine = MagicMock()
        mock_create_engine.return_value = mock_engine

        result = init_database()

        # Engine should be disposed
        mock_engine.dispose.assert_called_once()
        # Function should return None since engine is disposed
        assert result is None

    @patch(
        "local_deep_research.library.download_management.database_init.create_engine"
    )
    @patch("local_deep_research.library.download_management.database_init.Base")
    def test_init_database_disposes_engine_on_create_all_exception(
        self, mock_base, mock_create_engine
    ):
        """Test that init_database() disposes engine when create_all fails."""
        from local_deep_research.library.download_management.database_init import (
            init_database,
        )

        mock_engine = MagicMock()
        mock_create_engine.return_value = mock_engine
        mock_base.metadata.create_all.side_effect = Exception(
            "Table creation failed"
        )

        try:
            init_database()
        except Exception:
            pass

        # Engine should still be disposed in finally block
        mock_engine.dispose.assert_called_once()

    @patch(
        "local_deep_research.library.download_management.database_init.create_engine"
    )
    @patch("local_deep_research.library.download_management.database_init.Base")
    def test_init_database_calls_create_all(
        self, mock_base, mock_create_engine
    ):
        """Test that init_database() calls Base.metadata.create_all()."""
        from local_deep_research.library.download_management.database_init import (
            init_database,
        )

        mock_engine = MagicMock()
        mock_create_engine.return_value = mock_engine

        init_database()

        # Should create tables
        mock_base.metadata.create_all.assert_called_once_with(mock_engine)


class TestVerifyTableExistsEngineDisposal:
    """Tests for engine disposal in verify_table_exists()."""

    @patch(
        "local_deep_research.library.download_management.database_init.create_engine"
    )
    @patch(
        "local_deep_research.library.download_management.database_init.inspect"
    )
    def test_verify_table_exists_disposes_engine_when_table_exists(
        self, mock_inspect, mock_create_engine
    ):
        """Test that verify_table_exists() disposes engine when table exists."""
        from local_deep_research.library.download_management.database_init import (
            verify_table_exists,
        )

        mock_engine = MagicMock()
        mock_create_engine.return_value = mock_engine

        mock_inspector = MagicMock()
        mock_inspector.get_table_names.return_value = [
            "resource_download_status"
        ]
        mock_inspect.return_value = mock_inspector

        result = verify_table_exists()

        # Engine should be disposed
        mock_engine.dispose.assert_called_once()
        # Should return True since table exists
        assert result is True

    @patch(
        "local_deep_research.library.download_management.database_init.create_engine"
    )
    @patch(
        "local_deep_research.library.download_management.database_init.inspect"
    )
    def test_verify_table_exists_disposes_engine_when_table_missing(
        self, mock_inspect, mock_create_engine
    ):
        """Test that verify_table_exists() disposes engine when table is missing."""
        from local_deep_research.library.download_management.database_init import (
            verify_table_exists,
        )

        mock_engine = MagicMock()
        mock_create_engine.return_value = mock_engine

        mock_inspector = MagicMock()
        mock_inspector.get_table_names.return_value = ["other_table"]
        mock_inspect.return_value = mock_inspector

        result = verify_table_exists()

        # Engine should be disposed
        mock_engine.dispose.assert_called_once()
        # Should return False since table doesn't exist
        assert result is False

    @patch(
        "local_deep_research.library.download_management.database_init.create_engine"
    )
    @patch(
        "local_deep_research.library.download_management.database_init.inspect"
    )
    def test_verify_table_exists_disposes_engine_on_inspect_exception(
        self, mock_inspect, mock_create_engine
    ):
        """Test that verify_table_exists() disposes engine on inspect error."""
        from local_deep_research.library.download_management.database_init import (
            verify_table_exists,
        )

        mock_engine = MagicMock()
        mock_create_engine.return_value = mock_engine
        mock_inspect.side_effect = Exception("Inspection failed")

        try:
            verify_table_exists()
        except Exception:
            pass

        # Engine should still be disposed in finally block
        mock_engine.dispose.assert_called_once()

    @patch(
        "local_deep_research.library.download_management.database_init.create_engine"
    )
    @patch(
        "local_deep_research.library.download_management.database_init.inspect"
    )
    def test_verify_table_exists_disposes_engine_on_get_table_names_exception(
        self, mock_inspect, mock_create_engine
    ):
        """Test that verify_table_exists() disposes engine on get_table_names error."""
        from local_deep_research.library.download_management.database_init import (
            verify_table_exists,
        )

        mock_engine = MagicMock()
        mock_create_engine.return_value = mock_engine

        mock_inspector = MagicMock()
        mock_inspector.get_table_names.side_effect = Exception(
            "Cannot read tables"
        )
        mock_inspect.return_value = mock_inspector

        try:
            verify_table_exists()
        except Exception:
            pass

        # Engine should still be disposed in finally block
        mock_engine.dispose.assert_called_once()

    @patch(
        "local_deep_research.library.download_management.database_init.create_engine"
    )
    @patch(
        "local_deep_research.library.download_management.database_init.inspect"
    )
    def test_verify_table_exists_uses_inspect_function(
        self, mock_inspect, mock_create_engine
    ):
        """Test that verify_table_exists() uses SQLAlchemy inspect()."""
        from local_deep_research.library.download_management.database_init import (
            verify_table_exists,
        )

        mock_engine = MagicMock()
        mock_create_engine.return_value = mock_engine

        mock_inspector = MagicMock()
        mock_inspector.get_table_names.return_value = []
        mock_inspect.return_value = mock_inspector

        verify_table_exists()

        # Should call inspect with the engine
        mock_inspect.assert_called_once_with(mock_engine)
