# -*- coding: utf-8 -*-
"""读取 build_catalog.py 生成的接口目录。"""

from __future__ import annotations

import json
from functools import lru_cache
from pathlib import Path

CATALOG_PATH = Path(__file__).resolve().parent / "catalog.json"


@lru_cache(maxsize=1)
def load() -> list[dict]:
    if not CATALOG_PATH.is_file():
        raise FileNotFoundError(f"缺少 {CATALOG_PATH.name}，先运行 python mcp/build_catalog.py")
    data = json.loads(CATALOG_PATH.read_text(encoding="utf-8"))
    if not isinstance(data, list):
        raise ValueError("catalog.json 不是数组")
    return data


def by_id(api_id: str) -> dict | None:
    api_id = api_id.strip().lower()
    for row in load():
        if row.get("id") == api_id:
            return row
    return None


def categories() -> list[dict]:
    counts: dict[str, int] = {}
    for row in load():
        name = str(row.get("category") or "其他")
        counts[name] = counts.get(name, 0) + 1
    return [{"category": name, "count": count} for name, count in sorted(counts.items(), key=lambda item: (-item[1], item[0]))]


PREFERRED = {
    "天气": "weather",
    "备案": "icp",
    "快递": "express-pro",
    "物流": "express-pro",
    "企业": "company-search",
    "工商": "company-search",
    "条码": "barcode-gs1",
    "热搜": "hot-search",
}


def search(query: str = "", category: str = "", limit: int = 12) -> list[dict]:
    limit = max(1, min(30, int(limit)))
    query = query.strip().lower()
    category = category.strip()
    if not query and not category:
        return []
    scored: list[tuple[int, dict]] = []
    tokens = [part for part in query.replace("，", " ").replace(",", " ").split() if part]
    for row in load():
        if category and category not in str(row.get("category") or ""):
            continue
        api = str(row.get("id") or "")
        title = str(row.get("title") or "").lower()
        summary = str(row.get("summary") or "").lower()
        cat = str(row.get("category") or "").lower()
        params = str(row.get("params") or "").lower()
        score = 0
        if query:
            if query == api:
                score += 100
            elif query in api:
                score += 40
            if query in title:
                score += 35
            if query in summary:
                score += 12
            if query in cat:
                score += 4
            if query in params:
                score += 6
            if PREFERRED.get(query) == api:
                score += 20
            for token in tokens:
                if token == api:
                    score += 50
                elif token in title or token in api:
                    score += 8
        else:
            score = 1
        if score <= 0:
            continue
        scored.append((score, row))
    scored.sort(key=lambda item: (-item[0], str(item[1].get("id"))))
    out = []
    for _, row in scored[:limit]:
        out.append({
            "id": row.get("id"),
            "title": row.get("title"),
            "category": row.get("category"),
            "summary": row.get("summary"),
            "method": row.get("method"),
            "kyc": bool(row.get("kyc")),
            "media": bool(row.get("media")),
        })
    return out


def describe(api_id: str) -> dict:
    row = by_id(api_id)
    if row is None:
        return {
            "found": False,
            "id": api_id.strip().lower(),
            "hint": "本地目录没有这个 id。先 apizero_search。线上若是数据库中转接口，目录里不会出现。",
        }
    return {
        "found": True,
        "id": row.get("id"),
        "title": row.get("title"),
        "category": row.get("category"),
        "summary": row.get("summary"),
        "method": row.get("method"),
        "url": row.get("url"),
        "timeout_sec": row.get("timeout_sec"),
        "kyc": bool(row.get("kyc")),
        "media": bool(row.get("media")),
        "params": row.get("params") or "",
        "doc": row.get("doc") or "",
        "call_hint": _call_hint(row),
    }


def _call_hint(row: dict) -> str:
    hints = [
        "用 apizero_call，把参数放进 params。POST 会以 JSON 提交，网关会合并进表单字段。",
    ]
    if row.get("method") == "GET":
        hints.append("这个接口只接受 GET，不要带 JSON 体。")
    if row.get("kyc"):
        hints.append("这是实名/车牌核验。用户明确要核验，并且已经给出当事人数据时，才把 confirm_sensitive 设为 true。")
    if row.get("media"):
        hints.append("返回的 video_url、audio_url、video_list 保持原样，不要改成代理地址。")
    if row.get("id") == "ai-chat":
        hints.append("成功响应是 OpenAI chat.completion，没有 code 外壳。model 和 messages（或 prompt）必填。不确定模型是否仍在售时，把网关拒绝原文返回给用户。")
    return "".join(hints)
