"""
FastAPI application for Platform Service.
"""

import logging
import os
from typing import TYPE_CHECKING

import sqlalchemy as sa
from alembic import command
from alembic.config import Config
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

if TYPE_CHECKING:
    from ..component import PlatformServiceComponent

log = logging.getLogger(__name__)

app = FastAPI(
    title="Platform Service API",
    version="1.0.0",
    description="Platform configuration management API (agents, connectors, toolsets, deployments)",
)

# Global flag to track initialization (idempotent)
_dependencies_initialized = False


def _setup_alembic_config(database_url: str) -> Config:
    """
    Create and configure an Alembic Config object for community platform migrations.

    Args:
        database_url: Database connection string.

    Returns:
        Configured Alembic Config object.
    """
    alembic_cfg = Config()
    # Note: __file__ is in api/main.py, so we go up one level (..) to get to platform/
    alembic_cfg.set_main_option(
        "script_location",
        os.path.join(os.path.dirname(__file__), "..", "alembic"),
    )
    alembic_cfg.set_main_option("sqlalchemy.url", database_url)
    return alembic_cfg


def _run_community_migrations(database_url: str) -> None:
    """
    Run Alembic migrations for the community platform database schema.
    This includes any base tables defined in the community repo.

    Args:
        database_url: Database connection string.
    """
    try:
        from sqlalchemy import create_engine

        log.info("Starting community platform migrations...")
        engine = create_engine(database_url)
        inspector = sa.inspect(engine)
        existing_tables = inspector.get_table_names()

        if not existing_tables:
            log.info("Running initial community platform database setup")
            alembic_cfg = _setup_alembic_config(database_url)
            command.upgrade(alembic_cfg, "head")
            log.info("Community platform database migrations completed")
        else:
            log.info("Checking for community platform schema updates")
            alembic_cfg = _setup_alembic_config(database_url)
            command.upgrade(alembic_cfg, "head")
            log.info("Community platform database schema is current")
    except Exception as e:
        log.warning(
            "Community platform migration check failed: %s - attempting to run migrations",
            e,
        )
        try:
            alembic_cfg = _setup_alembic_config(database_url)
            command.upgrade(alembic_cfg, "head")
            log.info("Community platform database migrations completed")
        except Exception as migration_error:
            log.error("Community platform migration failed: %s", migration_error)
            log.error("Check database connectivity and permissions")
            raise RuntimeError(
                f"Community platform database migration failed: {migration_error}"
            ) from migration_error


def _run_enterprise_migrations(database_url: str) -> None:
    """
    Run migrations for enterprise platform features.
    This is optional and only runs if the enterprise package is available.

    Args:
        component: PlatformServiceComponent instance.
        database_url: Database connection string.
    """
    try:
        from solace_agent_mesh_enterprise.platform_service.migration_runner import run_migrations

        log.info("Starting enterprise platform migrations...")
        run_migrations(database_url)
        log.info("Enterprise platform migrations completed")
    except ImportError:
        log.debug("Enterprise platform module not found - skipping enterprise migrations")
    except Exception as e:
        log.error("Enterprise platform migration failed: %s", e)
        log.error("Enterprise platform features may be unavailable")
        raise RuntimeError(f"Enterprise platform database migration failed: {e}") from e


def _setup_database(database_url: str) -> None:
    """
    Initialize database connection and run all required migrations.
    Sets up both community and enterprise platform database schemas.

    This follows the same pattern as gateway/http_sse:
    1. Initialize database (create engine and SessionLocal)
    2. Run community migrations
    3. Run enterprise migrations (if available)

    Args:
        component: PlatformServiceComponent instance.
        database_url: Platform database URL (agents, connectors, deployments, toolsets) - REQUIRED
    """
    from . import dependencies

    # MIGRATION PHASE 1: DB is initialized in enterprise repo. In next phase, platform db will be initialized here
    # dependencies.init_database(database_url)
    # log.info("Platform database initialized - running migrations...")

    # MIGRATION PHASE 1: No community migrations yet - only enterprise migrations
    # _run_community_migrations(database_url)
    _run_enterprise_migrations(database_url)


def setup_dependencies(component: "PlatformServiceComponent", database_url: str):
    """
    Initialize dependencies for the Platform Service.

    This function is idempotent and safe to call multiple times.
    It sets up:
    1. Component instance reference
    2. Database connection
    3. Middleware (CORS, OAuth2)
    4. Routers (community and enterprise)

    Args:
        component: PlatformServiceComponent instance.
        database_url: Database connection string.
    """
    global _dependencies_initialized

    if _dependencies_initialized:
        log.debug("Platform service dependencies already initialized, skipping")
        return

    log.info("Initializing Platform Service dependencies...")

    # Store component reference for dependency injection
    from . import dependencies

    dependencies.set_component_instance(component)

    # Initialize database and run migrations
    if database_url:
        _setup_database(database_url)
        log.info("Platform database initialized with migrations")
    else:
        log.warning("No database URL provided - platform service will not function")

    # Setup middleware
    _setup_middleware(component)

    # Setup routers
    _setup_routers()

    _dependencies_initialized = True
    log.info("Platform Service dependencies initialized successfully")


async def _start_enterprise_platform_tasks(component: "PlatformServiceComponent") -> None:
    """
    Start enterprise platform background tasks if enterprise package is available.

    This follows the exact same pattern as WebUI Gateway:
    - Community calls enterprise function
    - Enterprise owns all background task logic
    - Graceful degradation if enterprise not available

    Background tasks (enterprise-only):
    - Heartbeat listener (deployer monitoring)
    - Deployment status checker (agent deployment monitoring)
    - Agent registry (tracks deployed agents)

    Args:
        component: PlatformServiceComponent instance
    """
    try:
        from solace_agent_mesh_enterprise.init_enterprise import (
            start_platform_background_tasks,
        )

        log.info("Starting enterprise platform background tasks...")
        await start_platform_background_tasks(component)
        log.info("Enterprise platform background tasks started successfully")

    except ImportError:
        log.info(
            "Enterprise package not available - platform background tasks will not start. "
            "Platform Service will run without deployment monitoring and deployer heartbeat tracking."
        )
    except RuntimeError as enterprise_err:
        log.warning(
            "Enterprise platform tasks disabled: %s - Platform Service will continue without deployment monitoring",
            enterprise_err,
        )
    except Exception as enterprise_err:
        log.error(
            "Failed to start enterprise platform tasks: %s - Platform Service will continue",
            enterprise_err,
            exc_info=True,
        )


def _setup_middleware(component: "PlatformServiceComponent"):
    """
    Add middleware to the FastAPI application.

    1. CORS middleware - allows cross-origin requests
    2. OAuth2 middleware - authentication (real token validation)

    Args:
        component: PlatformServiceComponent instance for configuration access.
    """
    # CORS middleware - automatically trust configured UI origins
    configured_origins = component.get_cors_origins().copy()

    # Automatically add frontend and platform service URLs as trusted origins
    # These are admin-controlled values that should always be trusted
    frontend_url = os.getenv("FRONTEND_SERVER_URL", "").strip()
    platform_url = os.getenv("PLATFORM_SERVICE_URL", "").strip()

    # Auto-construct frontend URL if not provided
    if not frontend_url:
        # Read WebUI Gateway configuration from environment variables
        fastapi_host = os.getenv("FASTAPI_HOST", "127.0.0.1").strip()
        fastapi_port = os.getenv("FASTAPI_PORT", "8000").strip()
        ssl_keyfile = os.getenv("SSL_KEYFILE", "").strip()
        ssl_certfile = os.getenv("SSL_CERTFILE", "").strip()

        # Determine protocol and port based on SSL configuration
        if ssl_keyfile and ssl_certfile:
            protocol = "https"
            port = os.getenv("FASTAPI_HTTPS_PORT", "8443").strip()
        else:
            protocol = "http"
            port = fastapi_port

        # Use 'localhost' if host is 127.0.0.1 for better compatibility
        host = "localhost" if fastapi_host == "127.0.0.1" else fastapi_host
        frontend_url = f"{protocol}://{host}:{port}"

        log.info(
            "FRONTEND_SERVER_URL not configured, auto-constructed from WebUI Gateway settings: %s",
            frontend_url
        )

    auto_trusted_origins = []
    if frontend_url:
        auto_trusted_origins.append(frontend_url)
    if platform_url:
        auto_trusted_origins.append(platform_url)

    # Combine and deduplicate
    allowed_origins = list(set(auto_trusted_origins + configured_origins))

    app.add_middleware(
        CORSMiddleware,
        allow_origins=allowed_origins,
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )
    log.info(f"CORS middleware added with origins: {allowed_origins}")
    if auto_trusted_origins:
        log.info(f"  Auto-added trusted origins: {auto_trusted_origins}")

    # OAuth2 authentication middleware
    from solace_agent_mesh.shared.auth.middleware import create_oauth_middleware

    oauth_middleware_class = create_oauth_middleware(component)
    app.add_middleware(oauth_middleware_class, component=component)

    use_auth = component.get_config("frontend_use_authorization", False)
    if use_auth:
        log.info("OAuth2 middleware added (real token validation enabled)")
    else:
        log.info("OAuth2 middleware added (development mode - frontend_use_authorization=false)")


def _setup_routers():
    """
    Mount community and enterprise routers to the FastAPI application.

    Community routers: Loaded from .routers (empty in Phase 1)
    Enterprise routers: Dynamically loaded from enterprise package if available
    """
    # Load community platform routers (empty in Phase 1)
    from .routers import get_community_platform_routers

    community_routers = get_community_platform_routers()
    for router_config in community_routers:
        app.include_router(
            router_config["router"],
            prefix=router_config["prefix"],
            tags=router_config["tags"],
        )
    log.info(f"Mounted {len(community_routers)} community platform routers")

    # Try to load enterprise platform routers
    try:
        from solace_agent_mesh_enterprise.platform_service.routers import get_enterprise_routers

        enterprise_routers = get_enterprise_routers()
        for router_config in enterprise_routers:
            app.include_router(
                router_config["router"],
                prefix=router_config["prefix"],
                tags=router_config["tags"],
            )
        log.info(f"Mounted {len(enterprise_routers)} enterprise platform routers")

    except ImportError:
        log.info(
            "No enterprise package detected - running in community mode (no platform endpoints available)"
        )
    except Exception as e:
        log.warning(f"Failed to load enterprise platform routers: {e}")

    from solace_agent_mesh.shared.exceptions.exception_handlers import register_exception_handlers
    register_exception_handlers(app)
    log.info("Registered shared exception handlers")


@app.get("/health", tags=["Health"])
async def health_check():
    """
    Platform Service health check endpoint.

    Returns:
        Dictionary with status and service name.
    """
    log.debug("Health check endpoint '/health' called")
    return {"status": "healthy", "service": "Platform Service"}
