from typing import Any, Dict, Optional

from langchain_core.tools import tool

from wiki_engine.service import (
    delete_by_file,
    delete_by_kb,
    diff_kb,
    evidence_search,
    get_stats,
    reconcile_kb,
    resolve_kb_reference,
    search_wiki,
    sync_file,
    sync_kb,
)


async def wiki_pointer_search(
    query: str,
    kb_id: Optional[str] = None,
    limit: int = 5,
) -> Dict[str, Any]:
    """Search local Wiki pointer pages and return related 11000 slice ids."""
    if not query or not query.strip():
        return {"success": False, "error": "query is empty", "items": []}
    return await search_wiki(query=query.strip(), kb_id=kb_id, limit=limit, include_slices=True)


async def wiki_evidence_search(
    query: str,
    kb_id: Optional[str] = None,
    limit: int = 5,
) -> Dict[str, Any]:
    """Return Wiki results in the unified evidence-like format."""
    if not query or not query.strip():
        return {"success": False, "error": "query is empty", "items": []}
    return await evidence_search(query=query.strip(), kb_id=kb_id, limit=limit)


async def wiki_admin_stats() -> Dict[str, Any]:
    return {"success": True, "stats": await get_stats()}


async def wiki_admin_sync_file(file_id: str, kb_id: Optional[str] = None, use_llm: bool = False) -> Dict[str, Any]:
    return await sync_file(file_id=file_id, kb_id=kb_id, use_llm=use_llm)


async def wiki_admin_sync_kb(
    kb_id: Optional[str] = None,
    kb_name: Optional[str] = None,
    limit: int = 20,
    use_llm: bool = False,
) -> Dict[str, Any]:
    target = await _resolve_kb_target(kb_id=kb_id, kb_name=kb_name)
    if not target.get("success"):
        return target
    result = await sync_kb(kb_id=target["kb_id"], limit=limit, use_llm=use_llm)
    result.update({"kb_name": target.get("kb_name", ""), "kb_path": target.get("kb_path", "")})
    return result


async def wiki_admin_diff_kb(
    kb_id: Optional[str] = None,
    kb_name: Optional[str] = None,
    include_children: bool = False,
    limit: int = 200,
) -> Dict[str, Any]:
    target = await _resolve_kb_target(kb_id=kb_id, kb_name=kb_name)
    if not target.get("success"):
        return target
    result = await diff_kb(kb_id=target["kb_id"], include_children=include_children, limit=limit)
    result.update({"kb_name": target.get("kb_name", ""), "kb_path": target.get("kb_path", "")})
    return result


async def wiki_admin_reconcile_kb(
    kb_id: Optional[str] = None,
    kb_name: Optional[str] = None,
    include_children: bool = False,
    limit: int = 200,
    sync_missing: bool = True,
    rebuild_stale: bool = True,
    delete_orphan: bool = False,
    use_llm: bool = False,
    dry_run: bool = True,
) -> Dict[str, Any]:
    target = await _resolve_kb_target(kb_id=kb_id, kb_name=kb_name)
    if not target.get("success"):
        return target
    result = await reconcile_kb(
        kb_id=target["kb_id"],
        include_children=include_children,
        limit=limit,
        sync_missing=sync_missing,
        rebuild_stale=rebuild_stale,
        delete_orphan=delete_orphan,
        use_llm=use_llm,
        dry_run=dry_run,
    )
    result.update({"kb_name": target.get("kb_name", ""), "kb_path": target.get("kb_path", "")})
    return result


async def wiki_admin_delete_file(file_id: str) -> Dict[str, Any]:
    return await delete_by_file(file_id)


async def wiki_admin_delete_kb(kb_id: Optional[str] = None, kb_name: Optional[str] = None) -> Dict[str, Any]:
    target = await _resolve_kb_target(kb_id=kb_id, kb_name=kb_name)
    if not target.get("success"):
        return target
    result = await delete_by_kb(target["kb_id"])
    result.update({"kb_name": target.get("kb_name", ""), "kb_path": target.get("kb_path", "")})
    return result


async def _resolve_kb_target(kb_id: Optional[str] = None, kb_name: Optional[str] = None) -> Dict[str, Any]:
    if kb_id and str(kb_id).strip():
        return {"success": True, "kb_id": str(kb_id).strip(), "kb_name": "", "kb_path": ""}
    if kb_name and str(kb_name).strip():
        return await resolve_kb_reference(str(kb_name).strip())
    return {"success": False, "error": "kb_name is required", "matches": []}


@tool
async def wiki_pointer_search_tool(query: str, limit: int = 5) -> str:
    """Search Wiki pointer pages and format them for workflow prompts."""
    result = await wiki_pointer_search(query=query, limit=limit)
    if not result.get("success"):
        return ""
    parts = []
    for item in result.get("items", []):
        title = item.get("title", "")
        summary = item.get("summary", "")
        slice_ids = ", ".join(item.get("related_slice_ids", [])[:8])
        if title or summary:
            parts.append(f"[Wiki] {title}\n{summary}\nrelated_slice_ids: {slice_ids}")
    return "\n\n".join(parts)
