"""
Task registry for managing registered cron tasks.
"""

from typing import Dict, Type, List, Optional, TYPE_CHECKING
from django_cronjob_utils.exceptions import TaskNotFoundError

if TYPE_CHECKING:
    from django_cronjob_utils.base import CronTask


class ExecutionPattern:
    """Execution patterns for cron tasks."""
    
    STANDARD = 'standard'  # Check if already executed, skip if yes
    ALWAYS = 'always'  # Always execute (no duplicate check)
    RERUN_ON_FAILURE = 'rerun_on_failure'  # Only skip if previous execution succeeded
    RATE_LIMITED = 'rate_limited'  # Use locking to prevent concurrent execution


class TaskRegistry:
    """Centralized registry for cron tasks."""
    
    _tasks: Dict[str, Type['CronTask']] = {}
    _codes: Dict[str, str] = {}  # code -> name mapping
    _configs: Dict[str, dict] = {}  # name -> config mapping
    
    @classmethod
    def register(cls, name: str, code: str, task_class: Type['CronTask'], **config):
        """Register a task."""
        if name in cls._tasks:
            raise ValueError(f"Task '{name}' is already registered")
        if code in cls._codes:
            raise ValueError(f"Task code '{code}' is already registered")
        
        cls._tasks[name] = task_class
        cls._codes[code] = name
        cls._configs[name] = config
        
        # Apply configuration to task class
        task_class.task_name = name
        task_class.task_code = code
        task_class.execution_pattern = config.get('execution_pattern', ExecutionPattern.STANDARD)
        task_class.retry_on_failure = config.get('retry_on_failure', False)
        task_class.max_retries = config.get('max_retries', 0)
        task_class.retry_delay = config.get('retry_delay', 300)
        task_class.timeout = config.get('timeout')
    
    @classmethod
    def get_task(cls, name: str) -> Type['CronTask']:
        """Get task class by name."""
        if name not in cls._tasks:
            raise TaskNotFoundError(f"Task '{name}' not found. Available tasks: {', '.join(cls._tasks.keys())}")
        return cls._tasks[name]
    
    @classmethod
    def get_task_by_code(cls, code: str) -> Type['CronTask']:
        """Get task class by code."""
        if code not in cls._codes:
            raise TaskNotFoundError(f"Task code '{code}' not found")
        name = cls._codes[code]
        return cls.get_task(name)
    
    @classmethod
    def list_tasks(cls) -> List[str]:
        """List all registered task names."""
        return list(cls._tasks.keys())
    
    @classmethod
    def get_config(cls, name: str) -> dict:
        """Get configuration for a task."""
        return cls._configs.get(name, {})
    
    @classmethod
    def is_registered(cls, name: str) -> bool:
        """Check if a task is registered."""
        return name in cls._tasks
