"""
Module Interface - Standard ABC for all platform modules.

Every module in the platform must implement this interface to be
recognized and managed by the Module Registry.
"""
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Dict, List, Optional


class HealthState(str, Enum):
    """Health check states."""
    HEALTHY = 'healthy'
    DEGRADED = 'degraded'
    UNHEALTHY = 'unhealthy'
    UNKNOWN = 'unknown'


@dataclass
class HealthStatus:
    """Result of a module health check."""
    state: HealthState = HealthState.HEALTHY
    message: str = ''
    details: Dict[str, Any] = field(default_factory=dict)

    @property
    def is_healthy(self) -> bool:
        return self.state == HealthState.HEALTHY


@dataclass
class EntityDefinition:
    """
    Definition of a searchable entity within a module.
    
    Used by the Search & Index service to know what entities
    should be indexed and how.
    """
    name: str
    model_class: str  # Dotted path to Django model
    searchable_fields: List[str] = field(default_factory=list)
    filterable_fields: List[str] = field(default_factory=list)
    display_field: str = 'name'
    description: str = ''
    icon: str = ''


@dataclass
class EndpointDefinition:
    """Definition of a public API endpoint."""
    path: str
    method: str  # GET, POST, PUT, PATCH, DELETE
    name: str
    description: str = ''
    version: str = 'v1'
    is_public: bool = False
    required_permissions: List[str] = field(default_factory=list)


@dataclass
class TaskResult:
    """Result of processing a workflow task."""
    success: bool
    data: Dict[str, Any] = field(default_factory=dict)
    error: Optional[str] = None
    next_step: Optional[str] = None


class ModuleInterface(ABC):
    """
    Standard interface for all platform modules.
    
    Every module must implement this interface to:
    - Register itself with the Module Registry
    - Declare searchable entities for the Search service
    - Handle workflow tasks
    - Subscribe to and handle events
    - Report health status
    - Declare API endpoints
    
    Example implementation:
    
        class PLMModule(ModuleInterface):
            def get_module_info(self) -> Dict[str, Any]:
                return {
                    'name': 'plm',
                    'display_name': 'Product Lifecycle Management',
                    'version': '1.0.0',
                    'category': 'Operations',
                    'description': 'Manage product lifecycle from design to retirement',
                }
            
            def get_searchable_entities(self) -> List[EntityDefinition]:
                return [
                    EntityDefinition(
                        name='Part',
                        model_class='apps.modules.plm.models.Part',
                        searchable_fields=['name', 'part_number', 'description'],
                        filterable_fields=['status', 'category', 'created_at'],
                    ),
                ]
            ...
    """

    @abstractmethod
    def get_module_info(self) -> Dict[str, Any]:
        """
        Return module identification and metadata.
        
        Must include:
        - name: Unique module identifier (lowercase, underscores)
        - display_name: Human-readable name
        - version: Semver version string
        - category: Module category
        - description: Module description
        
        Optional:
        - icon, color, tags, dependencies
        """
        ...

    @abstractmethod
    def get_searchable_entities(self) -> List[EntityDefinition]:
        """
        Return list of entities that should be indexed by the Search service.
        
        Each entity defines which fields are searchable and filterable.
        """
        ...

    @abstractmethod
    def handle_workflow_task(
        self,
        task_id: str,
        task_type: str,
        context: Dict[str, Any],
    ) -> TaskResult:
        """
        Process a workflow task assigned to this module.
        
        Called by the Workflow Engine when a service/script task
        references this module.
        
        Args:
            task_id: Unique task identifier
            task_type: Task type key from the workflow definition
            context: Task context with input variables
            
        Returns:
            TaskResult with success status and output data
        """
        ...

    @abstractmethod
    def subscribe_to_events(self) -> List[str]:
        """
        Return list of event types this module subscribes to.
        
        Event types use dot notation: 'domain.entity.action'
        Example: ['plm.part.created', 'workflow.task.completed']
        """
        ...

    @abstractmethod
    def handle_event(self, event_type: str, event_data: Dict[str, Any]) -> None:
        """
        Process a received event.
        
        Called when an event matching one of the subscribed types is published.
        
        Args:
            event_type: The event type string
            event_data: The full event envelope data
        """
        ...

    @abstractmethod
    def health_check(self) -> HealthStatus:
        """
        Return the current health status of the module.
        
        Should check:
        - Database connectivity
        - External service dependencies
        - Resource availability (disk, memory)
        - Any critical subsystem status
        """
        ...

    @abstractmethod
    def get_api_endpoints(self) -> List[EndpointDefinition]:
        """
        Return list of public API endpoints provided by this module.
        
        Used for API documentation, routing validation, and
        permission configuration.
        """
        ...

    def get_provided_permissions(self) -> List[str]:
        """
        Return list of permission codenames this module provides.
        
        Override to declare custom permissions.
        Default returns an empty list.
        """
        return []

    def get_default_settings(self) -> Dict[str, Any]:
        """
        Return default settings for this module.
        
        Override to provide module-specific settings schema.
        Default returns an empty dict.
        """
        return {}

    def on_install(self, tenant_id: str) -> None:
        """
        Called when the module is installed for a tenant.
        
        Override to perform setup tasks (e.g., create default data).
        """
        pass

    def on_uninstall(self, tenant_id: str) -> None:
        """
        Called when the module is uninstalled from a tenant.
        
        Override to perform cleanup tasks.
        """
        pass
