"""
Knowledge lookup tools — plugin docs, changelogs, Paper docs.

Provides structured access to documentation for:
  - Plugin docs: WorldGuard, WorldEdit, CoreProtect, EssentialsX, LuckPerms
  - Minecraft changelogs: version history, what changed when
  - Paper server docs: Paper-specific configuration and behavior

Each function returns {content, url, ok} for the model to consume.
"""

import logging
import re
import requests
from typing import Any, Dict, Optional

log = logging.getLogger(__name__)

TIMEOUT = 12

# ── Plugin documentation wiki URLs ────────────────────────────────────────

PLUGIN_DOCS = {
    "worldguard": {
        "base_url": "https://worldguard.enginehub.org/en/latest",
        "search_url": "https://worldguard.enginehub.org/en/latest/search.html",
        "wiki_prefix": "WorldGuard",
        "pages": {
            "region": "/regions/",
            "flag": "/regions/flags/",
            "region flags": "/regions/flags/",
            "define": "/regions/commands/",
            "commands": "/regions/commands/",
            "priority": "/regions/priorities/",
            "global": "/regions/global-region/",
            "build": "/regions/flags/#build-flags",
            "pvp": "/regions/flags/#pvp",
            "mob": "/regions/flags/#mob-spawning",
            "entry": "/regions/flags/#entry-and-exit",
            "greeting": "/regions/flags/#greeting-and-farewell",
            "chest": "/regions/flags/#chest-access",
            "heal": "/regions/flags/#heal-and-feed",
        },
    },
    "worldedit": {
        "base_url": "https://worldedit.enginehub.org/en/latest",
        "wiki_prefix": "WorldEdit",
        "pages": {
            "selection": "/usage/regions/selections/",
            "clipboard": "/usage/clipboard/",
            "generation": "/usage/generation/",
            "brush": "/usage/brushes/",
            "pattern": "/usage/patterns/",
            "mask": "/usage/masks/",
            "transform": "/usage/transforms/",
            "schematic": "/usage/saving/",
            "sphere": "/usage/generation/#sphere",
            "cylinder": "/usage/generation/#cylinder",
            "pyramid": "/usage/generation/#pyramid",
            "fill": "/usage/filling/",
            "drain": "/usage/utilities/#drain",
            "smooth": "/usage/utilities/#smooth",
            "replace": "/usage/regions/operations/#replace",
            "stack": "/usage/regions/operations/#stack",
            "copy": "/usage/clipboard/#copy-and-cut",
            "paste": "/usage/clipboard/#paste",
        },
    },
    "coreprotect": {
        "base_url": "https://docs.coreprotect.net",
        "wiki_prefix": "CoreProtect",
        "github_url": "https://raw.githubusercontent.com/PlayPro/CoreProtect/master/README.md",
        "pages": {
            "inspect": "/commands/#inspect",
            "rollback": "/commands/#rollback",
            "restore": "/commands/#restore",
            "lookup": "/commands/#lookup",
            "status": "/commands/#status",
            "parameter": "/commands/#parameters",
            "time": "/commands/#time-parameters",
            "radius": "/commands/#radius-parameters",
            "action": "/commands/#action-parameters",
            "user": "/commands/#user-parameters",
            "block": "/commands/#block-parameters",
        },
    },
    "essentialsx": {
        "base_url": "https://essinfo.xeya.me/commands.php",
        "wiki_url": "https://essentialsx.net/wiki",
        "wiki_prefix": "EssentialsX",
        "pages": {
            "home": "?filter=home",
            "warp": "?filter=warp",
            "tp": "?filter=tp",
            "economy": "?filter=eco",
            "kit": "?filter=kit",
            "nick": "?filter=nick",
            "god": "?filter=god",
            "fly": "?filter=fly",
            "heal": "?filter=heal",
            "feed": "?filter=feed",
            "speed": "?filter=speed",
            "back": "?filter=back",
            "spawn": "?filter=spawn",
            "balance": "?filter=balance",
            "pay": "?filter=pay",
            "seen": "?filter=seen",
            "broadcast": "?filter=broadcast",
        },
    },
    "luckperms": {
        "base_url": "https://luckperms.net/wiki",
        "wiki_prefix": "LuckPerms",
        "pages": {
            "user": "/Usage#user-commands",
            "group": "/Usage#group-commands",
            "permission": "/Usage#permission-commands",
            "parent": "/Usage#parent-commands",
            "meta": "/Usage#meta-commands",
            "prefix": "/Usage#meta-commands",
            "weight": "/Weight",
            "context": "/Context",
            "inheritance": "/Usage#parent-commands",
            "temporary": "/Usage#permission-commands",
            "track": "/Usage#track-commands",
            "verbose": "/Usage#verbose",
        },
    },
}


def _fetch_page_text(url: str, max_chars: int = 2000) -> str:
    """Fetch a URL and extract text content."""
    try:
        r = requests.get(url, timeout=TIMEOUT, headers={"User-Agent": "Mortdecai/0.5"})
        r.raise_for_status()
        html = r.text

        # Strip HTML tags for a rough text extraction
        text = re.sub(r'<script[^>]*>[\s\S]*?</script>', '', html)
        text = re.sub(r'<style[^>]*>[\s\S]*?</style>', '', html)
        text = re.sub(r'<nav[^>]*>[\s\S]*?</nav>', '', text)
        text = re.sub(r'<header[^>]*>[\s\S]*?</header>', '', text)
        text = re.sub(r'<footer[^>]*>[\s\S]*?</footer>', '', text)
        text = re.sub(r'<[^>]+>', ' ', text)
        text = re.sub(r'\s+', ' ', text).strip()

        # Try to find the main content area
        # Look for the section most relevant to the query
        return text[:max_chars]
    except Exception as e:
        return f"Failed to fetch {url}: {e}"


def _wiki_api_search(wiki_base: str, query: str) -> Dict[str, Any]:
    """Search a MediaWiki-based wiki."""
    try:
        r = requests.get(
            f"{wiki_base}/api.php",
            params={"action": "opensearch", "search": query, "limit": 3, "format": "json"},
            timeout=TIMEOUT,
        )
        results = r.json()
        if len(results) >= 4 and results[1]:
            title = results[1][0]
            url = results[3][0] if len(results) > 3 and results[3] else ""

            # Get extract
            r2 = requests.get(
                f"{wiki_base}/api.php",
                params={
                    "action": "query", "prop": "extracts",
                    "exintro": True, "explaintext": True,
                    "titles": title, "format": "json",
                },
                timeout=TIMEOUT,
            )
            pages = r2.json().get("query", {}).get("pages", {})
            for page in pages.values():
                extract = page.get("extract", "")
                if extract:
                    return {"content": extract[:2000], "url": url, "ok": True}
        return {"content": f"No results for: {query}", "url": "", "ok": False}
    except Exception as e:
        return {"content": str(e), "url": "", "ok": False}


# ── Plugin docs lookup ─────────────────────────────────────────────────────

def plugin_docs_lookup(plugin: str, query: str) -> Dict[str, Any]:
    """Look up plugin documentation."""
    plugin = plugin.lower().strip()
    if plugin not in PLUGIN_DOCS:
        return {"content": f"Unknown plugin: {plugin}. Known: {', '.join(PLUGIN_DOCS.keys())}", "url": "", "ok": False}

    info = PLUGIN_DOCS[plugin]
    base_url = info["base_url"]
    query_lower = query.lower()

    # Try to match a known page first
    best_page = None
    best_score = 0
    for keyword, path in info.get("pages", {}).items():
        score = sum(1 for word in keyword.split() if word in query_lower)
        if score > best_score:
            best_score = score
            best_page = path

    if best_page:
        url = base_url + best_page if not best_page.startswith("?") else base_url + best_page
        content = _fetch_page_text(url)
        if len(content) > 100:
            return {"content": content, "url": url, "ok": True}

    # Fallback: try the CoreProtect GitHub README
    if plugin == "coreprotect" and info.get("github_url"):
        try:
            r = requests.get(info["github_url"], timeout=TIMEOUT)
            if r.ok:
                # Find relevant section in README
                text = r.text
                for line in text.split("\n"):
                    if query_lower.split()[0] in line.lower():
                        start = text.index(line)
                        return {"content": text[start:start+2000], "url": info["github_url"], "ok": True}
                return {"content": text[:2000], "url": info["github_url"], "ok": True}
        except Exception:
            pass

    # Fallback: search Minecraft wiki for the plugin
    result = _wiki_api_search("https://minecraft.wiki", f"{info['wiki_prefix']} {query}")
    if result.get("ok"):
        return result

    # Last resort: generic search
    return {
        "content": f"Could not find specific docs for {plugin} '{query}'. Try the wiki at {base_url}",
        "url": base_url,
        "ok": False,
    }


# ── Changelog lookup ───────────────────────────────────────────────────────

def changelog_lookup(query: str, version: str = None) -> Dict[str, Any]:
    """Look up Minecraft version changelog."""
    # Use Minecraft Wiki for version history
    if version:
        search_term = f"Java Edition {version}"
    else:
        search_term = f"Java Edition 1.21"

    # If query mentions specific content, search for it in the version page
    if query:
        search_term = f"{search_term} {query}"

    # Search the Minecraft Wiki
    result = _wiki_api_search("https://minecraft.wiki", search_term)
    if result.get("ok"):
        return {
            "content": result["content"],
            "version": version or "1.21",
            "url": result["url"],
            "ok": True,
        }

    # Try searching just the query on the wiki
    if query:
        result = _wiki_api_search("https://minecraft.wiki", query)
        if result.get("ok"):
            return {
                "content": result["content"],
                "version": version or "unknown",
                "url": result["url"],
                "ok": True,
            }

    return {
        "content": f"No changelog info found for {version or 'latest'}: {query}",
        "version": version or "unknown",
        "url": "",
        "ok": False,
    }


# ── Paper docs lookup ──────────────────────────────────────────────────────

PAPER_DOCS_BASE = "https://docs.papermc.io/paper"

def paper_docs_lookup(query: str) -> Dict[str, Any]:
    """Look up Paper server documentation."""
    # PaperMC docs are at docs.papermc.io — try fetching relevant pages
    query_lower = query.lower()

    # Map common queries to known pages
    page_map = {
        "config": "/reference/configuration/global-configuration",
        "world config": "/reference/configuration/world-configuration",
        "paper-world": "/reference/configuration/world-configuration",
        "paper-global": "/reference/configuration/global-configuration",
        "async": "/dev/api/async-events",
        "chunk": "/dev/api/chunk-system",
        "timings": "/dev/api/misc/timings",
        "plugin": "/dev/getting-started/plugin-yml",
        "permission": "/dev/api/event-api/handler-lists",
        "anti-xray": "/admin/anti-xray",
        "optimization": "/admin/how-to/anti-lag",
        "spark": "/admin/how-to/profiling",
    }

    best_page = None
    for keyword, path in page_map.items():
        if keyword in query_lower:
            best_page = path
            break

    if best_page:
        url = PAPER_DOCS_BASE + best_page
        content = _fetch_page_text(url)
        if len(content) > 100:
            return {"content": content, "url": url, "ok": True}

    # Fallback to Minecraft wiki search for Paper-specific topics
    result = _wiki_api_search("https://minecraft.wiki", f"Paper server {query}")
    if result.get("ok"):
        return result

    return {
        "content": f"No Paper docs found for: {query}. Check {PAPER_DOCS_BASE}",
        "url": PAPER_DOCS_BASE,
        "ok": False,
    }


# ── Dispatcher ─────────────────────────────────────────────────────────────

def handle_knowledge_tool(tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
    """Dispatch a knowledge lookup tool call."""
    if tool_name == "plugin.docs_lookup":
        return plugin_docs_lookup(
            plugin=arguments.get("plugin", ""),
            query=arguments.get("query", ""),
        )
    elif tool_name == "minecraft.changelog_lookup":
        return changelog_lookup(
            query=arguments.get("query", ""),
            version=arguments.get("version"),
        )
    elif tool_name == "paper.docs_lookup":
        return paper_docs_lookup(
            query=arguments.get("query", ""),
        )
    elif tool_name == "minecraft.wiki_lookup":
        return _wiki_api_search("https://minecraft.wiki", arguments.get("query", ""))
    else:
        return {"content": f"Unknown tool: {tool_name}", "url": "", "ok": False}
