"""Retry utilities for processors."""

import asyncio
import logging
from typing import Any, Callable, TypeVar

from .processor_types import RetryConfig

logger = logging.getLogger(__name__)

T = TypeVar('T')


def async_retry(max_attempts: int = 3, backoff_factor: float = 2.0):
    """Simplified async retry decorator."""

    def decorator(func: Callable[..., T]) -> Callable[..., T]:
        async def wrapper(*args, **kwargs) -> T:
            for attempt in range(max_attempts):
                try:
                    return await func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_attempts - 1:
                        logger.error(f"Final retry attempt failed for {func.__name__}: {e}")
                        raise
                    
                    delay = backoff_factor ** attempt
                    logger.warning(f"Retry attempt {attempt + 1}/{max_attempts} failed for {func.__name__}, retrying in {delay}s: {e}")
                    await asyncio.sleep(delay)
            
            # This should never be reached, but just in case
            raise RuntimeError(f"All {max_attempts} retry attempts failed for {func.__name__}")

        return wrapper

    return decorator


class RetryManager:
    """Manages retry operations with configurable strategies."""

    def __init__(self, config: RetryConfig):
        self.config = config

    async def execute_with_retry(self, operation: Callable[..., T], *args, **kwargs) -> T:
        """Execute an operation with retry logic."""
        
        @async_retry(max_attempts=self.config.max_attempts, backoff_factor=self.config.backoff_factor)
        async def retry_operation():
            return await operation(*args, **kwargs)
        
        return await retry_operation()

    def should_retry(self, exception: Exception) -> bool:
        """Determine if an exception should trigger a retry."""
        # Add custom retry logic here based on exception type
        return True
