from typing import Dict, Any, Type
from flask import current_app

from common.utils.cache.base import CacheHandler
from common.utils.cache.crewai_configuration import SpecialistProcessedConfig
from common.utils.cache.crewai_config_processor import BaseCrewAIConfigProcessor


class CrewAIProcessedConfigCacheHandler(CacheHandler[SpecialistProcessedConfig]):
    """Handles caching of processed specialist configurations"""
    handler_name = 'crewai_processed_config_cache'

    def __init__(self, region):
        super().__init__(region, 'crewai_processed_config')
        self.configure_keys('tenant_id', 'specialist_id')

    def _to_cache_data(self, instance: SpecialistProcessedConfig) -> Dict[str, Any]:
        """Convert SpecialistProcessedConfig to cache data"""
        return instance.to_dict()

    def _from_cache_data(self, data: Dict[str, Any], **kwargs) -> SpecialistProcessedConfig:
        """Create SpecialistProcessedConfig from cache data"""
        return SpecialistProcessedConfig.from_dict(data)

    def _should_cache(self, value: Dict[str, Any]) -> bool:
        """Validate cache data"""
        required_keys = {'agents', 'tasks', 'tools'}
        if not all(key in value for key in required_keys):
            current_app.logger.warning(f'CrewAI Processed Config Cache missing required keys: {required_keys}')
            return False
        return bool(value['agents'] or value['tasks'])

    def get_specialist_config(self, tenant_id: int, specialist_id: int) -> SpecialistProcessedConfig:
        """
        Get or create processed configuration for a specialist

        Args:
            tenant_id: Tenant ID
            specialist_id: Specialist ID

        Returns:
            Processed specialist configuration

        Raises:
            ValueError: If specialist not found or processor not configured
        """

        def creator_func(tenant_id: int, specialist_id: int) -> SpecialistProcessedConfig:
            # Create processor instance and process config
            processor = BaseCrewAIConfigProcessor(tenant_id, specialist_id)
            return processor.process_config()

        return self.get(
            creator_func,
            tenant_id=tenant_id,
            specialist_id=specialist_id
        )

    def invalidate_tenant_specialist(self, tenant_id: int, specialist_id: int):
        """Invalidate cache for a specific tenant's specialist"""
        self.invalidate(
            tenant_id=tenant_id,
            specialist_id=specialist_id
        )
        current_app.logger.info(
            f"Invalidated cache for tenant {tenant_id} specialist {specialist_id}"
        )


def register_specialist_cache_handlers(cache_manager) -> None:
    """Register specialist cache handlers with cache manager"""
    cache_manager.register_handler(
        CrewAIProcessedConfigCacheHandler,
        'eveai_chat_workers'
    )