"""
Author: Vasiliy Zdanovskiy
email: vasilyvz@gmail.com

Lifespan management utilities for MCP Proxy Adapter API.
"""

import signal
from types import FrameType
from contextlib import asynccontextmanager
from typing import Any, AsyncContextManager, AsyncIterator, Callable, Dict, Optional

from fastapi import FastAPI

from mcp_proxy_adapter.core.logging import get_global_logger
from mcp_proxy_adapter.core.path_utils import (
    ensure_application_path,
    ensure_registered_modules_paths,
)
from .registration_manager import RegistrationManager, set_stop_flag_sync


class LifespanManager:
    """Manager for application lifespan events."""

    def __init__(self) -> None:
        """Initialize lifespan manager."""
        self.logger = get_global_logger()
        self.registration_manager = RegistrationManager()

    def create_lifespan(
        self,
        config_path: Optional[str] = None,
        current_config: Optional[Dict[str, Any]] = None,
    ) -> Callable[[FastAPI], AsyncContextManager[None]]:
        """
        Create lifespan manager for the FastAPI application.

        Args:
            config_path: Path to configuration file (optional)
            current_config: Current configuration data (optional)

        Returns:
            Lifespan context manager
        """

        def signal_handler(signum: int, frame: Optional[FrameType]) -> None:
            """Handle interrupt signals (SIGINT, SIGTERM) by setting stop flag."""
            _ = frame
            logger = get_global_logger()
            logger.info(f"🛑 Received signal {signum}, setting stop flag...")
            set_stop_flag_sync(True)

        # Register signal handlers for graceful shutdown
        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)

        @asynccontextmanager
        async def lifespan(app: FastAPI) -> AsyncIterator[None]:
            """Lifespan context manager."""
            # Startup
            logger = get_global_logger()
            try:
                logger.info("=" * 80)
                logger.info("🚀 LIFESPAN STARTUP CALLED")
                logger.info("=" * 80)
                logger.info("Starting MCP Proxy Adapter")

                # CRITICAL: Ensure application path is in PYTHONPATH for spawn mode
                # This ensures that custom modules are importable in child processes
                try:
                    added_paths = ensure_application_path(config_path)
                    if added_paths:
                        logger.info(
                            f"✅ Added application paths to PYTHONPATH for spawn mode: {added_paths}"
                        )

                    # Also ensure registered modules' paths are available
                    registered_paths = ensure_registered_modules_paths()
                    if registered_paths:
                        logger.info(
                            f"✅ Added registered module paths to PYTHONPATH: {registered_paths}"
                        )
                except Exception as path_error:
                    logger.warning(
                        f"⚠️ Failed to ensure application paths for spawn mode: {path_error}"
                    )

                logger.info(
                    f"🔍 lifespan function: current_config parameter value: {current_config}"
                )
                logger.info(
                    f"🔍 lifespan function: current_config is None: {current_config is None}"
                )

                # Start heartbeat task only if registration is enabled
                # Check if registration is enabled before calling start_heartbeat
                logger = get_global_logger()
                logger.info(
                    f"🔍 Lifespan: current_config is {'None' if current_config is None else 'not None'}"
                )
                if current_config:
                    logger.info(
                        f"🔍 Lifespan: current_config type: {type(current_config)}"
                    )
                    logger.info(
                        f"🔍 Lifespan: current_config keys: {list(current_config.keys()) if hasattr(current_config, 'keys') else 'no keys'}"
                    )
                    if hasattr(current_config, "keys"):
                        logger.info(
                            f"🔍 Lifespan: current_config['registration'] exists: {'registration' in current_config}"
                        )
                        if "registration" in current_config:
                            reg_section = current_config.get("registration")
                            logger.info(
                                f"🔍 Lifespan: registration section type: {type(reg_section)}"
                            )
                            logger.info(
                                f"🔍 Lifespan: registration section: {reg_section}"
                            )

                    registration_enabled = False
                    # Check SimpleConfigModel first
                    try:
                        from mcp_proxy_adapter.config import get_config

                        cfg = get_config()
                        logger.info(f"🔍 SimpleConfigModel: cfg type: {type(cfg)}")
                        logger.info(
                            f"🔍 SimpleConfigModel: hasattr(cfg, 'model'): {hasattr(cfg, 'model')}"
                        )
                        if hasattr(cfg, "model"):
                            logger.info(
                                f"🔍 SimpleConfigModel: cfg.model type: {type(cfg.model)}"
                            )
                            logger.info(
                                f"🔍 SimpleConfigModel: hasattr(cfg.model, 'registration'): {hasattr(cfg.model, 'registration')}"
                            )
                            if hasattr(cfg.model, "registration"):
                                reg_model = cfg.model.registration
                                logger.info(
                                    f"🔍 SimpleConfigModel: reg_model type: {type(reg_model)}"
                                )
                                logger.info(
                                    f"🔍 SimpleConfigModel: reg_model.enabled: {reg_model.enabled}, reg_model.auto_on_startup: {reg_model.auto_on_startup}"
                                )
                                registration_enabled = (
                                    reg_model.enabled and reg_model.auto_on_startup
                                )
                                logger.info(
                                    f"🔍 Registration enabled check (SimpleConfigModel): {registration_enabled}"
                                )
                    except Exception as e:
                        logger.info(f"🔍 SimpleConfigModel check failed: {e}")
                        import traceback

                        logger.info(
                            f"🔍 SimpleConfigModel check traceback: {traceback.format_exc()}"
                        )

                    # Check registration section
                    if not registration_enabled:
                        registration_config = current_config.get("registration") or {}
                        if registration_config:
                            reg_enabled = registration_config.get("enabled", False)
                            reg_auto_startup = registration_config.get(
                                "auto_on_startup", True
                            )
                            registration_enabled = reg_enabled and reg_auto_startup

                    logger.info(
                        f"🔍 FINAL registration_enabled: {registration_enabled}"
                    )
                    if registration_enabled:
                        logger.info("✅ Registration enabled, starting heartbeat task")
                        try:
                            await self.registration_manager.start_heartbeat(
                                current_config
                            )
                        except Exception as e:
                            logger.error(
                                f"❌ Failed to start heartbeat task: {e}", exc_info=True
                            )
                            # Don't fail startup if heartbeat fails - server should still work
                    else:
                        logger.info(
                            "⚠️ Registration is disabled, skipping heartbeat task"
                        )
                else:
                    logger.info("⚠️ current_config is None, skipping heartbeat task")

                # Initialize queue manager if queuemgr is available
                try:
                    from mcp_proxy_adapter.integrations.queuemgr_integration import (
                        init_global_queue_manager,
                    )

                    # Read queue manager config from current_config or global config
                    queue_config = None
                    if current_config and "queue_manager" in current_config:
                        queue_config = current_config.get("queue_manager", {})
                    else:
                        # Try to get from global config
                        try:
                            from mcp_proxy_adapter.config import get_config

                            cfg = get_config()
                            if hasattr(cfg, "model") and hasattr(
                                cfg.model, "queue_manager"
                            ):
                                queue_config = {
                                    "enabled": cfg.model.queue_manager.enabled,
                                    "in_memory": cfg.model.queue_manager.in_memory,
                                    "registry_path": cfg.model.queue_manager.registry_path,
                                    "shutdown_timeout": cfg.model.queue_manager.shutdown_timeout,
                                    "max_concurrent_jobs": cfg.model.queue_manager.max_concurrent_jobs,
                                    "max_queue_size": cfg.model.queue_manager.max_queue_size,
                                    "per_job_type_limits": cfg.model.queue_manager.per_job_type_limits,
                                    "completed_job_retention_seconds": cfg.model.queue_manager.completed_job_retention_seconds,
                                    "command_timeout": cfg.model.queue_manager.command_timeout,
                                    "stop_job_wait_timeout": cfg.model.queue_manager.stop_job_wait_timeout,
                                }
                        except Exception as e:
                            logger.debug(
                                f"Could not read queue config from global config: {e}"
                            )

                    # Use defaults if config not found
                    if queue_config is None:
                        queue_config = {}

                    # Only initialize if enabled (default: True)
                    if queue_config.get("enabled", True):
                        await init_global_queue_manager(
                            registry_path=queue_config.get("registry_path"),
                            shutdown_timeout=queue_config.get("shutdown_timeout", 30.0),
                            max_concurrent_jobs=queue_config.get(
                                "max_concurrent_jobs", 10
                            ),
                            in_memory=queue_config.get("in_memory", True),
                            max_queue_size=queue_config.get("max_queue_size"),
                            per_job_type_limits=queue_config.get("per_job_type_limits"),
                            completed_job_retention_seconds=queue_config.get(
                                "completed_job_retention_seconds", 21600
                            ),
                            command_timeout=queue_config.get("command_timeout"),
                            stop_job_wait_timeout=queue_config.get(
                                "stop_job_wait_timeout"
                            ),
                        )
                        logger.info("✅ Queue manager initialized")
                    else:
                        logger.info("⚠️ Queue manager is disabled in configuration")
                except ImportError:
                    logger.debug("Queue manager not available (queuemgr not installed)")
                except Exception as e:
                    logger.warning(f"⚠️ Queue manager initialization failed: {e}")
                    # Don't fail startup if queue manager fails - server should still work

                # WebSocket /ws and job push: always on (server pushes job results via WS, no config)
                try:
                    from mcp_proxy_adapter.core.job_push.lifespan_wiring import (
                        startup_job_push,
                    )

                    await startup_job_push(app, current_config)
                except Exception as jp_err:
                    logger.warning("⚠️ Job push startup failed: %s", jp_err)
            except Exception as e:
                logger.error(f"❌ Lifespan startup failed: {e}", exc_info=True)
                # Don't fail startup - let the server start anyway
                # The error is logged, but the server should still be able to handle requests

            yield

            # Shutdown
            get_global_logger().info("Shutting down MCP Proxy Adapter")
            await self.registration_manager.stop()
            try:
                from mcp_proxy_adapter.core.job_push.lifespan_wiring import (
                    shutdown_job_push,
                )

                await shutdown_job_push(app)
            except Exception as jp_err:
                get_global_logger().warning("⚠️ Job push shutdown failed: %s", jp_err)

            # Shutdown queue manager if initialized
            try:
                from mcp_proxy_adapter.integrations.queuemgr_integration import (
                    shutdown_global_queue_manager,
                )

                await shutdown_global_queue_manager()
                get_global_logger().info("✅ Queue manager stopped")
            except ImportError:
                pass  # Queue manager not available
            except Exception as e:
                get_global_logger().warning(f"⚠️ Queue manager shutdown failed: {e}")

        return lifespan
