"""Unit tests for retry utilities."""

from unittest.mock import Mock, patch

import pytest

from augint_billing_lib.utils_retry import retry


@pytest.mark.unit
class TestRetry:
    """Test retry decorator."""

    def test_successful_call_no_retry(self):
        """Test successful call doesn't retry."""
        mock_func = Mock(return_value="success")

        @retry((ValueError,))
        def test_func():
            return mock_func()

        result = test_func()

        assert result == "success"
        assert mock_func.call_count == 1

    def test_retry_on_exception(self):
        """Test retry on specified exception."""
        mock_func = Mock(side_effect=[ValueError("error"), "success"])

        @retry((ValueError,), tries=2, base=0.01)
        def test_func():
            return mock_func()

        with patch("time.sleep"):  # Speed up test
            result = test_func()

        assert result == "success"
        assert mock_func.call_count == 2

    def test_retry_exhausted(self):
        """Test exception raised when retries exhausted."""
        mock_func = Mock(side_effect=ValueError("persistent error"))

        @retry((ValueError,), tries=3, base=0.01)
        def test_func():
            return mock_func()

        with patch("time.sleep"), pytest.raises(ValueError, match="persistent error"):
            test_func()

        assert mock_func.call_count == 3

    def test_no_retry_on_different_exception(self):
        """Test no retry on non-specified exception."""
        mock_func = Mock(side_effect=TypeError("wrong type"))

        @retry((ValueError,), tries=3)
        def test_func():
            return mock_func()

        with pytest.raises(TypeError, match="wrong type"):
            test_func()

        assert mock_func.call_count == 1

    def test_retry_with_multiple_exceptions(self):
        """Test retry with multiple exception types."""
        mock_func = Mock(side_effect=[ValueError("error1"), TypeError("error2"), "success"])

        @retry((ValueError, TypeError), tries=3, base=0.01)
        def test_func():
            return mock_func()

        with patch("time.sleep"):
            result = test_func()

        assert result == "success"
        assert mock_func.call_count == 3
