from __future__ import annotations

import contextlib
import logging
import shutil

from agents import set_tracing_disabled

from .agent_runtime import build_agent
from .chat_service import ChatService
from .config import Settings, apply_runtime_environment
from .db import ChatHistoryStore
from .mcp_runtime import MCPRuntime
from .ui import build_demo


LOGGER = logging.getLogger("openkite")


def _configure_logging() -> None:
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s %(levelname)s [%(name)s] %(message)s",
    )


def _validate_runtime_dependencies() -> None:
    if shutil.which("npx") is None:
        raise RuntimeError(
            "npx was not found in PATH. Install Node.js before starting openkite."
        )


def run_chat_app(settings: Settings) -> None:
    """Start the OpenKite Gradio chat application."""
    _configure_logging()
    set_tracing_disabled(True)
    apply_runtime_environment(settings)
    _validate_runtime_dependencies()

    store = ChatHistoryStore(settings.db_path)
    store.initialize()
    LOGGER.info("Chat history DB ready: %s", settings.db_path)

    runtime = MCPRuntime(settings)
    agent = build_agent(settings, runtime)
    chat_service = ChatService(agent, store)
    demo = build_demo(chat_service)

    @contextlib.asynccontextmanager
    async def _lifespan(app):
        await runtime.connect()
        LOGGER.info("Connected to Kite and Firecrawl MCP servers.")
        yield
        await runtime.close()
        LOGGER.info("MCP runtime closed.")

    demo.launch(
        server_name=settings.host,
        server_port=settings.port,
        share=settings.share,
        app_kwargs={"lifespan": _lifespan},
    )
