"""Recovery manager for coordinating multiple recovery strategies."""

import asyncio
import json
import logging
from typing import Any, Callable, Dict, List, Optional

from ...errors import TraxError, ErrorCode, ErrorCategory, ErrorSeverity
from ...logging import get_logger
from .base import RecoveryStrategyBase, RecoveryContext, RecoveryStrategy, RecoveryPriority

logger = get_logger(__name__)


class RecoveryManager:
    """Manages multiple recovery strategies."""
    
    def __init__(self):
        self.strategies: List[RecoveryStrategyBase] = []
        self.logger = get_logger(f"{__name__}.RecoveryManager")
    
    def add_strategy(self, strategy: RecoveryStrategyBase):
        """Add a recovery strategy."""
        self.strategies.append(strategy)
        self.logger.info(f"Added recovery strategy: {strategy.name}")
    
    def remove_strategy(self, strategy_name: str):
        """Remove a recovery strategy by name."""
        self.strategies = [s for s in self.strategies if s.name != strategy_name]
        self.logger.info(f"Removed recovery strategy: {strategy_name}")
    
    async def attempt_recovery(self, context: RecoveryContext) -> Optional[Any]:
        """Attempt recovery using available strategies."""
        self.logger.info(f"Attempting recovery for {context.operation_id}")
        
        # Sort strategies by priority
        sorted_strategies = sorted(
            self.strategies,
            key=lambda s: list(RecoveryPriority).index(s.priority)
        )
        
        for strategy in sorted_strategies:
            if not await strategy.can_recover(context):
                continue
            
            if not await strategy.should_attempt(context):
                continue
            
            context.attempts += 1
            context.strategy = RecoveryStrategy(strategy.name)
            
            try:
                self.logger.info(f"Trying recovery strategy: {strategy.name}")
                result = await strategy.execute(context)
                context.success = True
                context.result = result
                self.logger.info(f"Recovery successful with strategy: {strategy.name}")
                return result
            except Exception as e:
                self.logger.warning(f"Recovery strategy {strategy.name} failed: {e}")
                context.error = e if isinstance(e, TraxError) else TraxError(str(e))
        
        self.logger.error(f"All recovery strategies failed for {context.operation_id}")
        return None
    
    def get_available_strategies(self) -> List[str]:
        """Get list of available strategy names."""
        return [s.name for s in self.strategies]
    
    def get_strategy_by_name(self, name: str) -> Optional[RecoveryStrategyBase]:
        """Get strategy by name."""
        for strategy in self.strategies:
            if strategy.name == name:
                return strategy
        return None
