from __future__ import annotations

import os
from contextlib import asynccontextmanager
from typing import TYPE_CHECKING

from fastapi import FastAPI

from niannian.http.auth import BearerAuthMiddleware, resolve_http_auth, validate_http_auth
from niannian.http.routes.auth import create_auth_router
from niannian.http.routes.admin_users import create_admin_users_router
from niannian.http.routes.tenant_push import create_tenant_push_router
from niannian.http.routes.tenant_fetch import create_tenant_fetch_router
from niannian.http.routes.tenant_init_admin import create_tenant_init_admin_router
from niannian.http.routes.tenant_bootstrap import create_tenant_bootstrap_router
from niannian.http.routes.agent_fetch import create_agent_fetch_router
from niannian.http.routes.adult import create_adult_router
from niannian.http.routes.bridge import create_bridge_router
from niannian.http.routes.chat import create_chat_router
from niannian.http.routes.chat_attachments import create_chat_attachments_router
from niannian.http.routes.chat_mentions import create_chat_mentions_router
from niannian.http.routes.chat_user_stickers import create_chat_user_stickers_router
from niannian.http.routes.chat_jobs import create_chat_jobs_router
from niannian.http.routes.cognitive import create_cognitive_router
from niannian.http.routes.cloud import create_cloud_router
from niannian.http.routes.tier_ops import create_tier_ops_router
from niannian.http.routes.llm_config import create_llm_config_router
from niannian.http.routes.core import create_core_router
from niannian.http.routes.vault import create_vault_router
from niannian.http.routes.wiki import create_wiki_router
from niannian.http.routes.virtual_persona import create_virtual_persona_router
from niannian.http.routes.vp_deep_learn import create_vp_deep_learn_router
from niannian.http.routes.config_api import create_config_router
from niannian.http.routes.device import create_device_router
from niannian.http.routes.external_data import create_external_data_router
from niannian.http.routes.health import create_health_router
from niannian.http.routes.memory import create_memory_router
from niannian.http.routes.memory_admin import create_memory_admin_router
from niannian.http.routes.mcp_api import create_mcp_router
from niannian.http.routes.mcp_console import create_mcp_console_router
from niannian.http.routes.mrrr import create_mrrr_router
from niannian.http.routes.skills import create_skills_router
from niannian.http.routes.token import create_token_router
from niannian.http.routes.upload import create_upload_router
from niannian.http.routes.users import create_users_router
from niannian.http.routes.pinn_sync_client import create_pinn_sync_client_router
from niannian.http.static import mount_console

if TYPE_CHECKING:
    from niannian.client import NianNian


def create_app(nn: NianNian) -> FastAPI:
    mode = os.environ.get("NIANNIAN_MODE", (nn._config.get("runtime") or {}).get("mode", "auto"))
    validate_http_auth(nn._config, fail_fast=(mode == "docker"))
    auth_cfg = resolve_http_auth(nn._config)
    public_paths = list(auth_cfg.get("public_paths") or [])
    for path in ("/v1/auth/login", "/v1/auth/preflight", "/v1/auth/login-key"):
        if path not in public_paths:
            public_paths.append(path)
    auth_cfg["public_paths"] = public_paths

    mcp_cfg = nn._config.get("mcp", {})
    mcp_enabled = mcp_cfg.get("server", {}).get("enabled", True)
    mcp_mount = mcp_cfg.get("server", {}).get("mount_path", "/mcp")
    mcp_instance = None
    mcp_subapp = None

    if mcp_enabled:
        try:
            from niannian.mcp.server.app import create_mcp_app, mcp_lifespan
            from niannian.mcp.service import LocalNianNianService

            svc = LocalNianNianService(nn)
            mcp_instance, mcp_subapp = create_mcp_app(svc)
        except ImportError:
            mcp_instance = None
            mcp_subapp = None

    @asynccontextmanager
    async def lifespan(app: FastAPI):
        if mcp_instance is not None:
            async with mcp_lifespan(mcp_instance)(app):
                yield
        else:
            yield

    app = FastAPI(title="念念 NianNian", version="0.2.0", lifespan=lifespan)
    if auth_cfg.get("enabled"):
        app.add_middleware(
            BearerAuthMiddleware,
            enabled=True,
            bearer_token=auth_cfg.get("bearer_token"),
            public_paths=auth_cfg.get("public_paths"),
        )
    app.include_router(create_health_router(nn))
    app.include_router(create_auth_router(nn))
    app.include_router(create_admin_users_router(nn))
    app.include_router(create_tenant_push_router(nn))
    app.include_router(create_tenant_fetch_router(nn))
    app.include_router(create_tenant_init_admin_router(nn))
    app.include_router(create_tenant_bootstrap_router(nn))
    app.include_router(create_agent_fetch_router(nn))
    app.include_router(create_cloud_router(nn))
    app.include_router(create_tier_ops_router(nn))
    app.include_router(create_memory_router(nn))
    app.include_router(create_external_data_router(nn))
    app.include_router(create_memory_admin_router(nn))
    app.include_router(create_adult_router(nn))
    app.include_router(create_upload_router(nn))
    app.include_router(create_mrrr_router(nn))
    app.include_router(create_skills_router(nn))
    app.include_router(create_chat_router(nn))
    app.include_router(create_chat_attachments_router(nn))
    app.include_router(create_chat_mentions_router(nn))
    app.include_router(create_chat_user_stickers_router(nn))
    app.include_router(create_chat_jobs_router(nn))
    app.include_router(create_core_router(nn))
    app.include_router(create_cognitive_router(nn))
    app.include_router(create_wiki_router(nn))
    app.include_router(create_vault_router(nn))
    app.include_router(create_virtual_persona_router(nn))
    app.include_router(create_vp_deep_learn_router(nn))
    app.include_router(create_token_router(nn))
    app.include_router(create_users_router(nn))
    app.include_router(create_config_router(nn))
    app.include_router(create_llm_config_router(nn))
    app.include_router(create_mcp_router(nn))
    app.include_router(create_mcp_console_router(nn))
    app.include_router(create_device_router(nn))
    app.include_router(create_pinn_sync_client_router(nn))
    app.include_router(create_bridge_router(nn))

    if mcp_subapp is not None:
        app.mount(mcp_mount, mcp_subapp)

    mount_console(app, nn._config)

    return app


def run_server(nn: NianNian, *, host: str = "127.0.0.1", port: int = 18765) -> None:
    import uvicorn

    uvicorn.run(create_app(nn), host=host, port=port, log_level="info")
