# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/1-Chat.ipynb.

# %% auto 0
__all__ = ['spinner_style', 'user_messages', 'echo_responder', 'get_initial_messages', 'on_conn', 'on_disconn', 'create_chat_app']

# %% ../../nbs/1-Chat.ipynb 1
from fasthtml.common import *
from .cards import ChatCard, render_chat_list, mk_inp

# %% ../../nbs/1-Chat.ipynb 2
async def echo_responder(text: str) -> str:
    # simulate latency to show spinner
    await asyncio.sleep(0.2)
    return f"[DEBUG] You just said: {text}"


spinner_style = Style(
    """
    .spinner {
        display: inline-block;
        width: 20px;
        height: 20px;
        border: 3px solid rgba(0, 0, 0, 0.1);
        border-top-color: #333;
        border-radius: 50%;
        animation: spin 1s linear infinite;
    }
    
    @keyframes spin {
        to { transform: rotate(360deg); }
    }
    """
)

# %% ../../nbs/1-Chat.ipynb 3
user_messages: Dict[int, List[Dict[str, str]]] = {}


def get_initial_messages():
    return [
        {"role": "User", "content": "Hi"},
        {
            "role": "Assistant",
            "content": "Hello! I'm your helpful assistant. How can I assist you today?",
        },
    ]


def on_conn(ws, send):
    ws_id = id(ws)
    user_messages[ws_id] = get_initial_messages()


def on_disconn(ws):
    ws_id = id(ws)
    user_messages.pop(ws_id, None)


def create_chat_app(rt, responder=None):
    app = FastHTML(
        exts="ws",
        hdrs=(
            MarkdownJS(),
            HighlightJS(langs=["python", "javascript", "html", "css"]),
            spinner_style,
            confirm_script,
        ),
    )
    rt = app.route
    responder = echo_responder if responder is None else responder

    @rt("/")
    def home():
        return (
            Title("Supply Chain Analyst Chat"),
            Div(
                H1("Supply Chain RCA", style="text-align: center; padding: 1em;"),
                render_chat_list(get_initial_messages()),
                Form(
                    mk_inp(),
                    id="form",
                    ws_send=True,
                    style="display: flex; justify-content: center; margin-top: 20px; padding: 20px;",
                ),
                hx_ext="ws",
                ws_connect="/ws",
                style=f"font-family: monospace, sans-serif; margin: 0; padding: 0; background: {bg_color}; min-height: 100vh;",
            ),
        )

    @app.ws("/ws", conn=on_conn, disconn=on_disconn)
    async def ws_handler(msg: str, send, ws):
        # Get this user's messages using the WebSocket object
        ws_id = id(ws)
        messages = user_messages.get(ws_id)

        if messages is None:
            # Initialize if somehow missing
            messages = get_initial_messages()
            user_messages[ws_id] = messages

        # 1) Append user's message and send to this user only
        messages.append({"role": "User", "content": msg})
        await send(render_chat_list(messages))

        # 2) Insert assistant pending placeholder and send to this user
        ph_id = f"ph-{len(messages)}"
        messages.append(
            {"role": "Assistant", "content": "", "pending": True, "id": ph_id}
        )
        await send(render_chat_list(messages))

        # 3) Compute reply (sync/async), replace placeholder content, clear pending, send again
        reply_text = ""
        if responder:
            try:
                res = await responder(msg)
                reply_text = await res if inspect.isawaitable(res) else res
            except Exception as e:
                reply_text = f"Responder error: {e}"
        # replace pending
        for m in messages:
            if m.get("id") == ph_id:
                m.pop("pending", None)
                m["content"] = str(reply_text)
                break

        await send(render_chat_list(messages))

        # 4) Clear input for sender
        await send(mk_inp())
        await send(mk_inp())

    return app
