"""Nexus — Timmy's persistent conversational awareness space.

A conversational-only interface where Timmy maintains live memory context.
No tool use; pure conversation with memory integration and a teaching panel.

Routes:
    GET  /nexus              — render nexus page with live memory sidebar
    POST /nexus/chat         — send a message; returns HTMX partial
    POST /nexus/teach        — inject a fact into Timmy's live memory
    DELETE /nexus/history    — clear the nexus conversation history
"""

import asyncio
import logging
from datetime import datetime, timezone

from fastapi import APIRouter, Form, Request
from fastapi.responses import HTMLResponse

from dashboard.templating import templates
from timmy.memory_system import (
    get_memory_stats,
    recall_personal_facts_with_ids,
    search_memories,
    store_personal_fact,
)
from timmy.session import _clean_response, chat, reset_session

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/nexus", tags=["nexus"])

_NEXUS_SESSION_ID = "nexus"
_MAX_MESSAGE_LENGTH = 10_000

# In-memory conversation log for the Nexus session (mirrors chat store pattern
# but is scoped to the Nexus so it won't pollute the main dashboard history).
_nexus_log: list[dict] = []


def _ts() -> str:
    return datetime.now(timezone.utc).strftime("%H:%M:%S")


def _append_log(role: str, content: str) -> None:
    _nexus_log.append({"role": role, "content": content, "timestamp": _ts()})
    # Keep last 200 exchanges to bound memory usage
    if len(_nexus_log) > 200:
        del _nexus_log[:-200]


@router.get("", response_class=HTMLResponse)
async def nexus_page(request: Request):
    """Render the Nexus page with live memory context."""
    stats = get_memory_stats()
    facts = recall_personal_facts_with_ids()[:8]

    return templates.TemplateResponse(
        request,
        "nexus.html",
        {
            "page_title": "Nexus",
            "messages": list(_nexus_log),
            "stats": stats,
            "facts": facts,
        },
    )


@router.post("/chat", response_class=HTMLResponse)
async def nexus_chat(request: Request, message: str = Form(...)):
    """Conversational-only chat routed through the Nexus session.

    Does not invoke tool-use approval flow — pure conversation with memory
    context injected from Timmy's live memory store.
    """
    message = message.strip()
    if not message:
        return HTMLResponse("")
    if len(message) > _MAX_MESSAGE_LENGTH:
        return templates.TemplateResponse(
            request,
            "partials/nexus_message.html",
            {
                "user_message": message[:80] + "…",
                "response": None,
                "error": "Message too long (max 10 000 chars).",
                "timestamp": _ts(),
                "memory_hits": [],
            },
        )

    ts = _ts()

    # Fetch semantically relevant memories to surface in the sidebar
    try:
        memory_hits = await asyncio.to_thread(
            search_memories, query=message, limit=4
        )
    except Exception as exc:
        logger.warning("Nexus memory search failed: %s", exc)
        memory_hits = []

    # Conversational response — no tool approval flow
    response_text: str | None = None
    error_text: str | None = None
    try:
        raw = await chat(message, session_id=_NEXUS_SESSION_ID)
        response_text = _clean_response(raw)
    except Exception as exc:
        logger.error("Nexus chat error: %s", exc)
        error_text = "Timmy is unavailable right now. Check that Ollama is running."

    _append_log("user", message)
    if response_text:
        _append_log("assistant", response_text)

    return templates.TemplateResponse(
        request,
        "partials/nexus_message.html",
        {
            "user_message": message,
            "response": response_text,
            "error": error_text,
            "timestamp": ts,
            "memory_hits": memory_hits,
        },
    )


@router.post("/teach", response_class=HTMLResponse)
async def nexus_teach(request: Request, fact: str = Form(...)):
    """Inject a fact into Timmy's live memory from the Nexus teaching panel."""
    fact = fact.strip()
    if not fact:
        return HTMLResponse("")

    try:
        await asyncio.to_thread(store_personal_fact, fact)
        facts = await asyncio.to_thread(recall_personal_facts_with_ids)
        facts = facts[:8]
    except Exception as exc:
        logger.error("Nexus teach error: %s", exc)
        facts = []

    return templates.TemplateResponse(
        request,
        "partials/nexus_facts.html",
        {"facts": facts, "taught": fact},
    )


@router.delete("/history", response_class=HTMLResponse)
async def nexus_clear_history(request: Request):
    """Clear the Nexus conversation history."""
    _nexus_log.clear()
    reset_session(session_id=_NEXUS_SESSION_ID)
    return templates.TemplateResponse(
        request,
        "partials/nexus_message.html",
        {
            "user_message": None,
            "response": "Nexus conversation cleared.",
            "error": None,
            "timestamp": _ts(),
            "memory_hits": [],
        },
    )
