"""
@vibe-generated
Tests for S3 temporary file context manager.
"""

from unittest.mock import AsyncMock, Mock

import pytest

from reflector.utils.s3_temp_file import S3TemporaryFile


@pytest.mark.asyncio
async def test_successful_upload_and_cleanup():
    """Test that file is uploaded and cleaned up on success."""
    # Mock storage
    mock_storage = Mock()
    mock_storage.put_file = AsyncMock()
    mock_storage.get_file_url = AsyncMock(return_value="https://example.com/file.wav")
    mock_storage.delete_file = AsyncMock()

    # Use context manager
    async with S3TemporaryFile(mock_storage, "test/file.wav") as s3_file:
        url = await s3_file.upload(b"test data")
        assert url == "https://example.com/file.wav"
        assert s3_file.url == "https://example.com/file.wav"

    # Verify operations
    mock_storage.put_file.assert_called_once_with("test/file.wav", b"test data")
    mock_storage.get_file_url.assert_called_once_with("test/file.wav")
    mock_storage.delete_file.assert_called_once_with("test/file.wav")


@pytest.mark.asyncio
async def test_cleanup_on_exception():
    """Test that cleanup happens even when an exception occurs."""
    # Mock storage
    mock_storage = Mock()
    mock_storage.put_file = AsyncMock()
    mock_storage.get_file_url = AsyncMock(return_value="https://example.com/file.wav")
    mock_storage.delete_file = AsyncMock()

    # Use context manager with exception
    with pytest.raises(ValueError):
        async with S3TemporaryFile(mock_storage, "test/file.wav") as s3_file:
            await s3_file.upload(b"test data")
            raise ValueError("Simulated error during processing")

    # Verify cleanup still happened
    mock_storage.delete_file.assert_called_once_with("test/file.wav")


@pytest.mark.asyncio
async def test_no_cleanup_if_not_uploaded():
    """Test that cleanup is skipped if file was never uploaded."""
    # Mock storage
    mock_storage = Mock()
    mock_storage.delete_file = AsyncMock()

    # Use context manager without uploading
    async with S3TemporaryFile(mock_storage, "test/file.wav"):
        pass  # Don't upload anything

    # Verify no cleanup attempted
    mock_storage.delete_file.assert_not_called()


@pytest.mark.asyncio
async def test_cleanup_failure_is_logged_not_raised():
    """Test that cleanup failures are logged but don't raise exceptions."""
    # Mock storage
    mock_storage = Mock()
    mock_storage.put_file = AsyncMock()
    mock_storage.get_file_url = AsyncMock(return_value="https://example.com/file.wav")
    mock_storage.delete_file = AsyncMock(side_effect=Exception("Delete failed"))

    # Use context manager - should not raise
    async with S3TemporaryFile(mock_storage, "test/file.wav") as s3_file:
        await s3_file.upload(b"test data")

    # Verify delete was attempted (3 times due to retry)
    assert mock_storage.delete_file.call_count == 3


@pytest.mark.asyncio
async def test_upload_retry_on_failure():
    """Test that upload is retried on failure."""
    # Mock storage with failures then success
    mock_storage = Mock()
    mock_storage.put_file = AsyncMock(
        side_effect=[Exception("Network error"), None]  # Fail once, then succeed
    )
    mock_storage.get_file_url = AsyncMock(return_value="https://example.com/file.wav")
    mock_storage.delete_file = AsyncMock()

    # Use context manager
    async with S3TemporaryFile(mock_storage, "test/file.wav") as s3_file:
        url = await s3_file.upload(b"test data")
        assert url == "https://example.com/file.wav"

    # Verify upload was retried
    assert mock_storage.put_file.call_count == 2


@pytest.mark.asyncio
async def test_delete_retry_on_failure():
    """Test that delete is retried on failure."""
    # Mock storage
    mock_storage = Mock()
    mock_storage.put_file = AsyncMock()
    mock_storage.get_file_url = AsyncMock(return_value="https://example.com/file.wav")
    mock_storage.delete_file = AsyncMock(
        side_effect=[Exception("Network error"), None]  # Fail once, then succeed
    )

    # Use context manager
    async with S3TemporaryFile(mock_storage, "test/file.wav") as s3_file:
        await s3_file.upload(b"test data")

    # Verify delete was retried
    assert mock_storage.delete_file.call_count == 2


@pytest.mark.asyncio
async def test_properties_before_upload():
    """Test that properties work correctly before upload."""
    mock_storage = Mock()

    async with S3TemporaryFile(mock_storage, "test/file.wav") as s3_file:
        assert s3_file.url is None
        assert s3_file.uploaded is False
