"""Dash dev tools hooks for AI Chat integration."""

import asyncio
import json

import dash
import flask
from packaging.version import parse as _parse_version

from ._chat_rpc import DashAIChatRPC

dash_version = _parse_version(dash.__version__)


def _run_sync(coro):
    loop = asyncio.get_event_loop()
    return loop.run_until_complete(coro)


def install_hook():
    import nest_asyncio

    # Make asyncio stuff runs smoothly.
    # Prevent no loop and existing loop errors.
    nest_asyncio.apply()

    chat_rpc = DashAIChatRPC()

    try:
        # Register Chat component
        dash.hooks.devtool(  # type: ignore
            "dash_ai_chat_component",
            "DashAIChatComponent",
            {"id": "_dash-ai-chat"},
            position="left",
        )
    except Exception:
        return

    dash.hooks.script(
        [
            {"dev_package_path": "dash_ai_devtools.js", "namespace": "dash_ai_chat", "dev_only": True},
        ]
    )

    dash.hooks.stylesheet(
        [
            {"relative_package_path": "dash_ai_devtools.css", "namespace": "dash_ai_chat"},
        ]
    )

    @dash.hooks.route("_dash_ai_chat", methods=["POST"])
    def dash_ai_chat_rpc():
        data = flask.request.get_json()
        data = _run_sync(chat_rpc.handle_operation(data))
        return flask.jsonify(data)

    @dash.hooks.route("_dash_ai_chat_stream", methods=["POST"])
    def dash_ai_chat_stream():
        """SSE endpoint for streaming chat responses."""
        data = flask.request.get_json()

        def generate():
            async def async_generate():
                async for event in chat_rpc.send_message_stream(data):
                    event_type = event.get("event", "message")
                    event_data = json.dumps(event.get("data", {}))
                    yield f"event: {event_type}\ndata: {event_data}\n\n"

            # Run async generator synchronously
            loop = asyncio.get_event_loop()
            gen = async_generate()
            while True:
                try:
                    chunk = loop.run_until_complete(gen.__anext__())
                    yield chunk
                except StopAsyncIteration:
                    break

        return flask.Response(
            generate(),
            mimetype="text/event-stream",
            headers={
                "Cache-Control": "no-cache",
                "Connection": "keep-alive",
                "X-Accel-Buffering": "no",
            }
        )

    @dash.hooks.setup()
    def dash_ai_chat_setup(app):
        chat_rpc._app_setup = app


if hasattr(dash.hooks, "devtool"):
    install_hook()
