# agentic_chat_ui/views/chainlit_view.py
import asyncio
import logging
import os

import uvicorn
from agentic_chat_ui.src.settings import ChainlitViewRunnerRunnerSettings
from agentic_chat_ui.src.utils import load_class
from agentic_chat_ui.src.view_runners import ViewRunner
from agentic_chat_ui.src.view_runners.chainlit.callbacks import (
    ChainlitCallBackRegistrar,
)

# ruff: noqa: E402
from chainlit.config import DEFAULT_ROOT_PATH, config
from chainlit.server import app

_logger = logging.getLogger(__name__)


class ChainlitViewRunner(ViewRunner[ChainlitViewRunnerRunnerSettings]):

    def __init__(self, config: ChainlitViewRunnerRunnerSettings) -> None:
        super().__init__(config)

    def _register_callbacks(self) -> None:
        for callback_config in self.config.view.callbacks:
            registrar: ChainlitCallBackRegistrar = load_class(callback_config.module_path)(callback_config, self)
            registrar.register()

    def _run_chainlit_backend(self) -> None:
        root_path = DEFAULT_ROOT_PATH
        ssl_certfile = os.environ.get("CHAINLIT_SSL_CERT", None)
        ssl_keyfile = os.environ.get("CHAINLIT_SSL_KEY", None)
        ws_per_message_deflate_env = os.environ.get("UVICORN_WS_PER_MESSAGE_DEFLATE", "true")
        ws_per_message_deflate = ws_per_message_deflate_env.lower() in [
            "true",
            "1",
            "yes",
        ]
        ws_protocol = os.environ.get("UVICORN_WS_PROTOCOL", "auto")
        config.run.host = self.config.host
        config.run.port = self.config.port
        config.run.root_path = root_path
        log_level = "debug" if config.run.debug else "error"

        async def start() -> None:
            config = uvicorn.Config(
                app,
                host=self.config.host,
                port=self.config.port,
                ws=ws_protocol,
                log_level=log_level,
                ws_per_message_deflate=ws_per_message_deflate,
                ssl_keyfile=ssl_keyfile,
                ssl_certfile=ssl_certfile,
            )
            server = uvicorn.Server(config)
            await server.serve()

        # Run the asyncio event loop instead of uvloop to enable re entrance
        asyncio.run(start())
        # uvicorn.run(app, host=host, port=port, log_level=log_level)

    def run(self) -> None:
        _logger.info(f"Starting Chainlit UI | host={self.config.host} | " f"port={self.config.port}")
        self._register_callbacks()
        self._run_chainlit_backend()
