from __future__ import annotations

import argparse
import sys
from pathlib import Path

from mcp.server.fastmcp import FastMCP

from mikoshi.auth import email_from_token, is_expired, load_auth_state
from mikoshi.config import configure_external_libs, load_config
from mikoshi.indexing.index_store import IndexStore
from mikoshi.utils.types import SearchResult

mcp = FastMCP("mikoshi")

_config = load_config()
configure_external_libs(_config.quiet_external_libs)
_BANNER_PRINTED = False


def _format_index_root(path: Path) -> str:
    try:
        home = Path.home().resolve()
        resolved = path.expanduser().resolve()
        if resolved == home:
            return "~"
        if str(resolved).startswith(str(home) + "/"):
            return str(resolved).replace(str(home), "~", 1)
        return str(resolved)
    except Exception:
        return str(path)


def _print_banner() -> None:
    global _BANNER_PRINTED
    if _BANNER_PRINTED:
        return
    index_root = _format_index_root(_config.index_root)
    banner_lines = [
        "🔧 Starting Mikoshi MCP Tool Server...",
        "📝 Mode: stdio",
        "📋 Available tools: index_repo, search, status, clear_index",
        f"📁 Index root: {index_root}",
        "🔗 Waiting for MCP client connections...",
    ]
    for line in banner_lines:
        print(line, file=sys.stderr)
    _BANNER_PRINTED = True


def _auth_status_line() -> str:
    state = load_auth_state()
    if state and not is_expired(state):
        email = email_from_token(state.access_token) or "unknown"
        plan = state.plan.title() if state.plan else "Free"
        return f"🔓 Signed in — {email} ({plan})"
    return "🔒 Not signed in — Free mode"


def _result_to_dict(result: SearchResult) -> dict[str, object]:
    return {
        "relpath": result.relpath,
        "start_line": result.start_line,
        "end_line": result.end_line,
        "score": result.score,
        "snippet": result.snippet,
    }


@mcp.tool()
def index_repo(path: str) -> dict[str, object]:
    from mikoshi.indexing.indexer import index_repo as run_index

    result = run_index(path)
    return {
        "repo_id": result.repo_id,
        "chunks_indexed": result.chunks_indexed,
        "took_ms": result.took_ms,
    }


@mcp.tool()
def search(path: str, query: str, k: int = 8) -> list[dict[str, object]]:
    from mikoshi.retrieval.hybrid import search_repo

    results = search_repo(path, query, k)
    return [_result_to_dict(result) for result in results]


@mcp.tool()
def status(path: str) -> dict[str, object]:
    config = load_config()
    repo_root = Path(path).expanduser().resolve()
    store = IndexStore(repo_root, config.index_root)
    meta = store.load_meta()
    if not meta:
        return {
            "indexed": False,
            "chunks": 0,
            "last_index_time": None,
            "model": None,
        }
    return {
        "indexed": True,
        "chunks": meta.chunks,
        "last_index_time": meta.updated_at,
        "model": meta.model,
    }


@mcp.tool()
def clear_index(path: str) -> dict[str, object]:
    config = load_config()
    repo_root = Path(path).expanduser().resolve()
    store = IndexStore(repo_root, config.index_root)
    store.clear()
    return {"ok": True}


def main() -> None:
    parser = argparse.ArgumentParser(prog="mikoshi-mcp", add_help=True)
    parser.add_argument(
        "--quiet",
        action="store_true",
        help="Suppress startup banner",
    )
    args = parser.parse_args()
    print(_auth_status_line(), file=sys.stderr)
    if not args.quiet:
        _print_banner()
    mcp.run()


if __name__ == "__main__":
    main()
