"""Base classes and enums for recovery strategies."""

import asyncio
import json
import logging
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from datetime import datetime, timezone
from enum import Enum
from typing import Any, Callable, Dict, List, Optional, TypeVar, Union

from ...errors import TraxError, ErrorCode, ErrorCategory, ErrorSeverity
from ...logging import get_logger

logger = get_logger(__name__)

T = TypeVar('T')


class RecoveryStrategy(Enum):
    """Different recovery strategies for error handling."""
    FALLBACK = "fallback"
    GRACEFUL_DEGRADATION = "graceful_degradation"
    STATE_RECOVERY = "state_recovery"
    TRANSACTION_ROLLBACK = "transaction_rollback"
    RESOURCE_CLEANUP = "resource_cleanup"
    HEALTH_CHECK = "health_check"
    RETRY_WITH_BACKOFF = "retry_with_backoff"
    CACHE_FALLBACK = "cache_fallback"


class RecoveryPriority(Enum):
    """Priority levels for recovery strategies."""
    CRITICAL = "critical"
    HIGH = "high"
    MEDIUM = "medium"
    LOW = "low"


@dataclass
class RecoveryContext:
    """Context information for recovery operations."""
    operation_id: str
    correlation_id: str
    error: TraxError
    strategy: RecoveryStrategy
    priority: RecoveryPriority
    metadata: Dict[str, Any] = field(default_factory=dict)
    timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
    attempts: int = 0
    max_attempts: int = 3
    success: bool = False
    result: Optional[Any] = None


class RecoveryStrategyBase(ABC):
    """Base class for recovery strategies."""
    
    def __init__(self, name: str, priority: RecoveryPriority = RecoveryPriority.MEDIUM):
        self.name = name
        self.priority = priority
        self.logger = get_logger(f"{__name__}.{name}")
    
    @abstractmethod
    async def can_recover(self, context: RecoveryContext) -> bool:
        """Determine if this strategy can recover from the given error."""
        pass
    
    @abstractmethod
    async def execute(self, context: RecoveryContext) -> Any:
        """Execute the recovery strategy."""
        pass
    
    async def should_attempt(self, context: RecoveryContext) -> bool:
        """Determine if this strategy should be attempted."""
        return context.attempts < context.max_attempts
