"""
Hook system integration for django-cronjob-utils.

This module provides hook context and hook manager for cronjob operations,
allowing external code to inject custom logic before and after cronjob execution.
"""

from dataclasses import dataclass, field
from datetime import date
from typing import Any, Dict, Optional

# Try to import django-package-hooks, but make it optional
try:
    from django_package_hooks import HookContext, HookManager, HookRegistry
    HOOKS_AVAILABLE = True
except ImportError:
    HOOKS_AVAILABLE = False
    # Create stub implementations when hooks package is not available
    @dataclass(frozen=True)
    class HookContext:
        """Stub HookContext when django-package-hooks is not installed."""
        operation: str
        metadata: Dict[str, Any] = field(default_factory=dict)
    
    class HookRegistry:
        """Stub HookRegistry when django-package-hooks is not installed."""
        def register(self, *args, **kwargs):
            pass
        
        def register_operation(self, *args, **kwargs):
            pass
    
    class HookManager:
        """Stub HookManager when django-package-hooks is not installed."""
        def __init__(self, *args, **kwargs):
            self.registry = HookRegistry()
        
        def execute_pre_hooks(self, *args, **kwargs):
            pass
        
        def execute_post_hooks(self, *args, **kwargs):
            pass


@dataclass(frozen=True)
class CronjobHookContext(HookContext):
    """
    Context for cronjob hook execution.
    
    This context is passed to all hooks and contains information about
    the cronjob execution.
    
    Attributes:
        operation: The operation being performed ('execute')
        task_code: Unique code identifying the task
        task_name: Human-readable task name
        execution_date: Date for which the task is being executed
        execution_id: Database ID of the execution record (None for PRE hooks, set for POST hooks)
        execution_pattern: Execution pattern (STANDARD, ALWAYS, etc.)
        retry_count: Number of times this task has been retried
        options: Additional options passed to the task (force, rerun, etc.)
        metadata: Mutable dictionary for inter-hook communication
    
    Example:
        context = CronjobHookContext(
            operation='execute',
            task_code='A001',
            task_name='daily-report',
            execution_date=date(2024, 1, 15),
            execution_pattern='STANDARD'
        )
    """
    
    # Required fields (but need defaults because parent has defaults)
    task_code: str = ''
    task_name: str = ''
    execution_date: Optional[date] = None
    execution_pattern: str = 'STANDARD'
    # Optional fields
    execution_id: Optional[int] = None
    retry_count: int = 0
    options: Dict[str, Any] = field(default_factory=dict)


def get_cronjob_hook_manager() -> HookManager:
    """
    Get the global hook manager for cronjob operations.
    
    This function returns a HookManager configured with the cronjob registry.
    The registry is initialized with the 'execute' operation.
    
    Returns:
        HookManager instance for executing cronjob hooks
    
    Example:
        manager = get_cronjob_hook_manager()
        context = CronjobHookContext(...)
        
        try:
            manager.execute_pre_hooks(context)
        except HookRejectionError as e:
            print(f"Task rejected: {e.error_code}")
    """
    # Create registry with 'execute' operation
    # We use 'execute' as the main operation for cronjob execution
    if HOOKS_AVAILABLE:
        registry = HookRegistry(operations=['execute'])
        return HookManager(registry)
    else:
        # Return stub manager when hooks not available
        return HookManager()


# Global hook manager singleton for cronjob operations
_cronjob_hook_manager: Optional[HookManager] = None


def get_global_cronjob_hook_manager() -> HookManager:
    """
    Get the global singleton hook manager for cronjob operations.
    
    This ensures all cronjob tasks use the same hook registry, allowing
    hooks to be registered once and applied to all tasks.
    
    Returns:
        Global HookManager instance
    """
    global _cronjob_hook_manager
    if _cronjob_hook_manager is None:
        if HOOKS_AVAILABLE:
            # Create dedicated registry with 'execute' operation
            registry = HookRegistry(operations=['execute'])
            _cronjob_hook_manager = HookManager(registry)
        else:
            # Return stub manager when hooks not available
            _cronjob_hook_manager = HookManager()
    return _cronjob_hook_manager


def clear_cronjob_hooks():
    """
    Clear all registered cronjob hooks.
    
    This is primarily useful for testing to ensure a clean slate between tests.
    """
    global _cronjob_hook_manager
    if _cronjob_hook_manager is not None and HOOKS_AVAILABLE:
        _cronjob_hook_manager.registry.clear()
    _cronjob_hook_manager = None
