from __future__ import annotations

import json
from typing import TYPE_CHECKING, Any

from aicd.home import new_chat_session_id

if TYPE_CHECKING:
    from aicd.agent.tool_router import ToolRouter


def _require_session(router: ToolRouter) -> str | None:
    sid = getattr(router, "_chat_session_id", None)
    return sid if sid else None


async def _chat_new_session(router: ToolRouter, args: dict[str, Any]) -> dict[str, Any]:
    del args
    if router._chat_session_id is None:
        return {"ok": False, "error": "chat_new_session only available on main agent"}
    new_sid = new_chat_session_id(router._layout["data"])
    router.set_chat_session_id(new_sid)
    switch = getattr(router, "_chat_session_switch", None)
    if switch:
        switch(new_sid)
    return {
        "ok": True,
        "session_id": new_sid,
        "in_memory_context_cleared": True,
        "note": "Earlier turns stay in SQLite under the old session_id; new messages use the new session_id.",
    }


async def _chat_session_info(router: ToolRouter, args: dict[str, Any]) -> dict[str, Any]:
    del args
    sid = _require_session(router)
    if not sid:
        return {"ok": False, "error": "chat history only available on main agent session"}
    store = router._tasks.store
    conn = router._tasks.db_conn
    n = await store.count_chat_messages(conn, sid)
    sn = len(await store.list_chat_summaries(conn, sid, limit=500))
    cfg = router._cfg.agent
    return {
        "ok": True,
        "session_id": sid,
        "message_count": n,
        "summary_count": sn,
        "context_budget_tokens": cfg.context_budget_tokens,
        "chat_history_max_messages": cfg.chat_history_max_messages,
    }


async def _chat_history_list(router: ToolRouter, args: dict[str, Any]) -> dict[str, Any]:
    sid = _require_session(router)
    if not sid:
        return {"ok": False, "error": "chat history only available on main agent session"}
    limit = int(args.get("limit", 40))
    limit = max(1, min(200, limit))
    store = router._tasks.store
    conn = router._tasks.db_conn
    rows = await store.list_chat_messages_tail(conn, sid, limit=limit)
    items: list[dict[str, Any]] = []
    for r in rows:
        prev = (r.content or "")[:240].replace("\n", " ")
        item: dict[str, Any] = {
            "id": r.id,
            "role": r.role,
            "created_at": r.created_at,
            "content_preview": prev + ("…" if len(r.content or "") > 240 else ""),
        }
        if r.tool_name:
            item["tool_name"] = r.tool_name
        if r.tool_call_id:
            item["tool_call_id"] = r.tool_call_id
        if r.tool_calls_json:
            item["has_tool_calls"] = True
        items.append(item)
    return {"ok": True, "session_id": sid, "messages": items}


async def _chat_history_get(router: ToolRouter, args: dict[str, Any]) -> dict[str, Any]:
    sid = _require_session(router)
    if not sid:
        return {"ok": False, "error": "chat history only available on main agent session"}
    mid = int(args["message_id"])
    store = router._tasks.store
    conn = router._tasks.db_conn
    row = await store.get_chat_message(conn, mid)
    if row is None or row.session_id != sid:
        return {"ok": False, "error": "message not found for this session"}
    tool_calls: list[dict[str, Any]] | None = None
    if row.tool_calls_json:
        try:
            tc = json.loads(row.tool_calls_json)
            tool_calls = tc if isinstance(tc, list) else None
        except json.JSONDecodeError:
            tool_calls = None
    return {
        "ok": True,
        "message": {
            "id": row.id,
            "session_id": row.session_id,
            "role": row.role,
            "content": row.content,
            "created_at": row.created_at,
            "tool_calls": tool_calls,
            "tool_call_id": row.tool_call_id,
            "tool_name": row.tool_name,
        },
    }


async def _chat_save_summary(router: ToolRouter, args: dict[str, Any]) -> dict[str, Any]:
    sid = _require_session(router)
    if not sid:
        return {"ok": False, "error": "chat history only available on main agent session"}
    content = str(args.get("content") or "").strip()
    if not content:
        return {"ok": False, "error": "content is required"}
    covers = args.get("covers_up_to_message_id")
    cid = int(covers) if covers is not None else None
    store = router._tasks.store
    conn = router._tasks.db_conn
    rid = await store.append_chat_summary(
        conn, session_id=sid, content=content, covers_up_to_message_id=cid
    )
    return {"ok": True, "summary_id": rid}


async def _chat_summaries_list(router: ToolRouter, args: dict[str, Any]) -> dict[str, Any]:
    sid = _require_session(router)
    if not sid:
        return {"ok": False, "error": "chat history only available on main agent session"}
    limit = int(args.get("limit", 15))
    limit = max(1, min(100, limit))
    store = router._tasks.store
    conn = router._tasks.db_conn
    rows = await store.list_chat_summaries(conn, sid, limit=limit)
    return {
        "ok": True,
        "session_id": sid,
        "summaries": [
            {
                "id": r.id,
                "content": r.content,
                "covers_up_to_message_id": r.covers_up_to_message_id,
                "created_at": r.created_at,
            }
            for r in rows
        ],
    }


HANDLERS: dict[str, Any] = {
    "chat_new_session": _chat_new_session,
    "chat_session_info": _chat_session_info,
    "chat_history_list": _chat_history_list,
    "chat_history_get": _chat_history_get,
    "chat_save_summary": _chat_save_summary,
    "chat_summaries_list": _chat_summaries_list,
}
