"""Fallback provider implementations."""

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 FallbackProvider

logger = get_logger(__name__)


class CacheFallbackProvider(FallbackProvider):
    """Fallback provider that uses cached responses."""
    
    def __init__(self, cache_key: str, cache_store: Callable, cache_retrieve: Callable):
        super().__init__("cache", priority=1)
        self.cache_key = cache_key
        self.cache_store = cache_store
        self.cache_retrieve = cache_retrieve
    
    async def is_available(self) -> bool:
        """Check if cache is available."""
        try:
            cached_data = await self.cache_retrieve(self.cache_key)
            return cached_data is not None
        except Exception:
            return False
    
    async def execute(self, *args, **kwargs) -> Any:
        """Retrieve cached data."""
        try:
            cached_data = await self.cache_retrieve(self.cache_key)
            if cached_data is not None:
                self.logger.info(f"Cache hit for key: {self.cache_key}")
                return cached_data
            else:
                self.logger.warning(f"Cache miss for key: {self.cache_key}")
                return None
        except Exception as e:
            self.logger.error(f"Cache retrieval failed: {e}")
            return None


class ServiceFallbackProvider(FallbackProvider):
    """Fallback provider that uses alternative service endpoints."""
    
    def __init__(self, name: str, service_endpoint: str, service_client: Callable):
        super().__init__(name, priority=2)
        self.service_endpoint = service_endpoint
        self.service_client = service_client
    
    async def is_available(self) -> bool:
        """Check if service is available."""
        try:
            # Simple health check
            await asyncio.wait_for(self.service_client.health_check(), timeout=5.0)
            return True
        except Exception:
            return False
    
    async def execute(self, *args, **kwargs) -> Any:
        """Execute operation using alternative service."""
        try:
            result = await self.service_client.execute(*args, **kwargs)
            self.logger.info(f"Service {self.name} executed successfully")
            return result
        except Exception as e:
            self.logger.error(f"Service {self.name} execution failed: {e}")
            raise


class DefaultValueFallbackProvider(FallbackProvider):
    """Fallback provider that returns default values."""
    
    def __init__(self, name: str, default_value: Any):
        super().__init__(name, priority=3)
        self.default_value = default_value
    
    async def is_available(self) -> bool:
        """Default value provider is always available."""
        return True
    
    async def execute(self, *args, **kwargs) -> Any:
        """Return default value."""
        self.logger.info(f"Using default value for {self.name}")
        return self.default_value


# Convenience functions for common fallback scenarios
async def create_cache_fallback(
    cache_key: str,
    cache_store: Callable,
    cache_retrieve: Callable
) -> CacheFallbackProvider:
    """Create a cache fallback provider."""
    return CacheFallbackProvider(cache_key, cache_store, cache_retrieve)


async def create_service_fallback(
    name: str,
    service_endpoint: str,
    service_client: Callable
) -> ServiceFallbackProvider:
    """Create a service fallback provider."""
    return ServiceFallbackProvider(name, service_endpoint, service_client)


async def create_default_value_fallback(
    name: str,
    default_value: Any
) -> DefaultValueFallbackProvider:
    """Create a default value fallback provider."""
    return DefaultValueFallbackProvider(name, default_value)
