"""Tests for composite database with file backup storage."""

from unittest.mock import MagicMock, patch


from local_deep_research.storage.database_with_file_backup import (
    DatabaseWithFileBackupStorage,
)


class TestDatabaseWithFileBackupStorageInit:
    """Tests for DatabaseWithFileBackupStorage initialization."""

    def test_creates_db_storage(self, mock_session):
        """Should create database storage."""
        storage = DatabaseWithFileBackupStorage(mock_session)
        assert storage.db_storage is not None

    def test_file_storage_disabled_by_default(self, mock_session):
        """Should not create file storage by default."""
        storage = DatabaseWithFileBackupStorage(mock_session)
        assert storage.file_storage is None
        assert storage.enable_file_storage is False

    def test_creates_file_storage_when_enabled(self, mock_session):
        """Should create file storage when enabled."""
        with patch(
            "local_deep_research.storage.database_with_file_backup.FileReportStorage"
        ):
            storage = DatabaseWithFileBackupStorage(
                mock_session, enable_file_storage=True
            )
            assert storage.enable_file_storage is True


class TestSaveReport:
    """Tests for save_report method."""

    def test_saves_to_database(self, mock_session, sample_report_content):
        """Should save to database."""
        storage = DatabaseWithFileBackupStorage(mock_session)
        storage.db_storage = MagicMock()
        storage.db_storage.save_report.return_value = True

        result = storage.save_report("test-uuid", sample_report_content)

        assert result is True
        storage.db_storage.save_report.assert_called_once()

    def test_returns_false_when_db_fails(
        self, mock_session, sample_report_content
    ):
        """Should return False when database save fails."""
        storage = DatabaseWithFileBackupStorage(mock_session)
        storage.db_storage = MagicMock()
        storage.db_storage.save_report.return_value = False

        result = storage.save_report("test-uuid", sample_report_content)

        assert result is False

    def test_saves_to_file_when_enabled(
        self, mock_session, sample_report_content
    ):
        """Should save to file when file storage enabled."""
        storage = DatabaseWithFileBackupStorage(
            mock_session, enable_file_storage=True
        )
        storage.db_storage = MagicMock()
        storage.db_storage.save_report.return_value = True
        storage.file_storage = MagicMock()
        storage.file_storage.save_report.return_value = True

        result = storage.save_report("test-uuid", sample_report_content)

        assert result is True
        storage.file_storage.save_report.assert_called_once()

    def test_succeeds_even_if_file_fails(
        self, mock_session, sample_report_content
    ):
        """Should succeed even if file save fails."""
        storage = DatabaseWithFileBackupStorage(
            mock_session, enable_file_storage=True
        )
        storage.db_storage = MagicMock()
        storage.db_storage.save_report.return_value = True
        storage.file_storage = MagicMock()
        storage.file_storage.save_report.return_value = False

        result = storage.save_report("test-uuid", sample_report_content)

        assert result is True  # Still success because DB succeeded

    def test_handles_file_exception(self, mock_session, sample_report_content):
        """Should handle file storage exception gracefully."""
        storage = DatabaseWithFileBackupStorage(
            mock_session, enable_file_storage=True
        )
        storage.db_storage = MagicMock()
        storage.db_storage.save_report.return_value = True
        storage.file_storage = MagicMock()
        storage.file_storage.save_report.side_effect = Exception("file error")

        result = storage.save_report("test-uuid", sample_report_content)

        assert result is True  # Still success because DB succeeded


class TestGetReport:
    """Tests for get_report method."""

    def test_gets_from_database(self, mock_session, sample_report_content):
        """Should get from database."""
        storage = DatabaseWithFileBackupStorage(mock_session)
        storage.db_storage = MagicMock()
        storage.db_storage.get_report.return_value = sample_report_content

        result = storage.get_report("test-uuid")

        assert result == sample_report_content
        storage.db_storage.get_report.assert_called_once()

    def test_never_reads_from_file(self, mock_session, sample_report_content):
        """Should never read from file, only database."""
        storage = DatabaseWithFileBackupStorage(
            mock_session, enable_file_storage=True
        )
        storage.db_storage = MagicMock()
        storage.db_storage.get_report.return_value = sample_report_content
        storage.file_storage = MagicMock()

        storage.get_report("test-uuid")

        storage.file_storage.get_report.assert_not_called()


class TestDeleteReport:
    """Tests for delete_report method."""

    def test_deletes_from_database(self, mock_session):
        """Should delete from database."""
        storage = DatabaseWithFileBackupStorage(mock_session)
        storage.db_storage = MagicMock()
        storage.db_storage.delete_report.return_value = True

        result = storage.delete_report("test-uuid")

        assert result is True
        storage.db_storage.delete_report.assert_called_once()

    def test_deletes_from_file_when_enabled(self, mock_session):
        """Should delete from file when file storage enabled."""
        storage = DatabaseWithFileBackupStorage(
            mock_session, enable_file_storage=True
        )
        storage.db_storage = MagicMock()
        storage.db_storage.delete_report.return_value = True
        storage.file_storage = MagicMock()

        storage.delete_report("test-uuid")

        storage.file_storage.delete_report.assert_called_once()

    def test_skips_file_delete_when_db_fails(self, mock_session):
        """Should skip file delete when database delete fails."""
        storage = DatabaseWithFileBackupStorage(
            mock_session, enable_file_storage=True
        )
        storage.db_storage = MagicMock()
        storage.db_storage.delete_report.return_value = False
        storage.file_storage = MagicMock()

        storage.delete_report("test-uuid")

        storage.file_storage.delete_report.assert_not_called()

    def test_handles_file_delete_exception(self, mock_session):
        """Should handle file delete exception gracefully."""
        storage = DatabaseWithFileBackupStorage(
            mock_session, enable_file_storage=True
        )
        storage.db_storage = MagicMock()
        storage.db_storage.delete_report.return_value = True
        storage.file_storage = MagicMock()
        storage.file_storage.delete_report.side_effect = Exception(
            "delete error"
        )

        result = storage.delete_report("test-uuid")

        assert result is True  # Still returns db result


class TestGetReportWithMetadata:
    """Tests for get_report_with_metadata method."""

    def test_gets_from_database(self, mock_session):
        """Should get from database."""
        storage = DatabaseWithFileBackupStorage(mock_session)
        storage.db_storage = MagicMock()
        expected = {"content": "test", "metadata": {}}
        storage.db_storage.get_report_with_metadata.return_value = expected

        result = storage.get_report_with_metadata("test-uuid")

        assert result == expected


class TestReportExists:
    """Tests for report_exists method."""

    def test_checks_database(self, mock_session):
        """Should check database."""
        storage = DatabaseWithFileBackupStorage(mock_session)
        storage.db_storage = MagicMock()
        storage.db_storage.report_exists.return_value = True

        result = storage.report_exists("test-uuid")

        assert result is True
        storage.db_storage.report_exists.assert_called_once()
