"""Shared lifecycle mixin for singleton async managers.

Provides common start/stop lifecycle and singleton pattern for managers
that run async event loops.
"""

from __future__ import annotations

import asyncio
from typing import Any


class LifecycleMixin:
    """Mixin providing start/stop lifecycle and singleton pattern.
    
    Classes using this mixin must define:
    - _instance: ClassVar[Any | None] = None
    - _running: bool = False
    - _task: asyncio.Task | None = None
    - _logger_name: str (for logging)
    """
    
    _instance: Any | None = None
    _running: bool = False
    _task: asyncio.Task | None = None
    _logger_name: str = "lifecycle"
    
    @classmethod
    def get(cls) -> Any:
        """Get singleton instance."""
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance
    
    def start(self) -> None:
        """Start the event loop."""
        if self._running:
            return
        self._running = True
        self._task = asyncio.create_task(self._event_loop())
        # Logger message set by subclass
        self._log_started()
    
    def stop(self) -> None:
        """Stop the event loop."""
        self._running = False
        if self._task:
            self._task.cancel()
        self._log_stopped()
    
    def _log_started(self) -> None:
        """Log startup - override or use _logger_name."""
        from structlog import get_logger
        logger = get_logger(self._logger_name)
        logger.info(f"{self._logger_name}_started")
    
    def _log_stopped(self) -> None:
        """Log shutdown - override or use _logger_name."""
        from structlog import get_logger
        logger = get_logger(self._logger_name)
        logger.info(f"{self._logger_name}_stopped")
    
    async def _event_loop(self) -> None:
        """Main event loop - must be implemented by subclass."""
        raise NotImplementedError("Subclass must implement _event_loop()")
