#!/usr/bin/env python3
"""
安装仓库内置的 AgentPack 到本地 agentpacks 目录。

用法（server 必须先运行）：
    python scripts/install_builtin_packs.py

也可以不启动 server，直接写入 agentpacks_dir：
    python scripts/install_builtin_packs.py --offline

内置 pack 位置：agentexample/agentpacks/
安装目标：    ~/.agentpaas/data/agentpacks/   (desktop 模式)
              ~/LambdAgentDesktop/agentpacks/  (如果是 desktop 模式且未改数据目录)
"""
from __future__ import annotations

import argparse
import json
import os
import sys
import zipfile
import tempfile
from pathlib import Path


REPO_ROOT = Path(__file__).parent.parent.resolve()
PACKS_SRC  = REPO_ROOT / "agentexample" / "agentpacks"

BUILTIN_PACKS = [
    "research.top-journal-reviewer",
    "research.literature-mapper",
    "research.grant-planner",
]


def _zip_pack(pack_id: str, dest_dir: Path) -> str:
    pack_dir = PACKS_SRC / pack_id
    if not pack_dir.is_dir():
        sys.exit(f"❌  Pack 目录不存在: {pack_dir}")
    zip_path = str(dest_dir / f"{pack_id}.zip")
    with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf:
        for p in pack_dir.rglob("*"):
            if p.is_file():
                zf.write(p, p.relative_to(pack_dir))
    return zip_path


def _default_packs_dir() -> str:
    """读取 ~/.agentpaas/config.json 或按 desktop 模式默认值推断 agentpacks_dir。"""
    cfg = Path.home() / ".agentpaas" / "config.json"
    try:
        with open(cfg) as f:
            data = json.load(f) or {}
        data_dir = data.get("data_dir", "")
    except Exception:
        data_dir = ""
    if not data_dir:
        # desktop 默认
        data_dir = str(Path.home() / "LambdAgentDesktop")
    return os.path.join(data_dir, "agentpacks")


# ── 离线模式：直接调用 install_from_zip ──────────────────────────────────────

def install_offline(packs_dir: str, packs: list[str]) -> None:
    from agentpaas.engine.agentpack_store import install_from_zip, get_installed

    os.makedirs(packs_dir, exist_ok=True)
    print(f"\n安装目标目录: {packs_dir}\n")

    with tempfile.TemporaryDirectory() as td:
        for pack_id in packs:
            existing = get_installed(packs_dir, pack_id)
            if existing:
                print(f"  ✓  {pack_id} v{existing.version}  — 已安装，跳过")
                continue
            zip_path = _zip_pack(pack_id, Path(td))
            try:
                pack = install_from_zip(zip_path, packs_dir)
                print(f"  ✓  {pack_id} v{pack.version}  — 安装完成")
            except Exception as e:
                print(f"  ✗  {pack_id}  — 失败: {e}", file=sys.stderr)


# ── 在线模式：通过 HTTP API 安装（需要 server 运行）───────────────────────────

def install_online(base_url: str, api_key: str, packs: list[str]) -> None:
    try:
        import requests
    except ImportError:
        sys.exit("缺少依赖: pip install requests")

    session = requests.Session()
    if api_key:
        session.headers["Authorization"] = f"Bearer {api_key}"

    print(f"\n连接 server: {base_url}\n")

    # 先列出已安装
    try:
        r = session.get(f"{base_url}/api/v1/agentpacks", timeout=5)
        r.raise_for_status()
        already = {p["id"] for p in r.json().get("agentpacks", [])}
    except Exception as e:
        sys.exit(f"❌  无法连接 server: {e}\n    请先启动: uvicorn agentpaas.api.app:app --port 8000")

    with tempfile.TemporaryDirectory() as td:
        for pack_id in packs:
            if pack_id in already:
                print(f"  ✓  {pack_id}  — 已安装，跳过")
                continue
            zip_path = _zip_pack(pack_id, Path(td))
            r = session.post(
                f"{base_url}/api/v1/agentpacks/install",
                json={"zip_path": zip_path},
                timeout=30,
            )
            if r.status_code == 200:
                pack = r.json()["installed"]
                print(f"  ✓  {pack['id']} v{pack['version']}  — 安装完成")
            else:
                print(f"  ✗  {pack_id}  — HTTP {r.status_code}: {r.text[:120]}", file=sys.stderr)


# ── CLI ───────────────────────────────────────────────────────────────────────

def main() -> None:
    parser = argparse.ArgumentParser(
        description="安装仓库内置 AgentPack (research.* 三个 pack)",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
示例:
  # 离线安装（不需要 server 运行，推荐）
  python scripts/install_builtin_packs.py --offline

  # 在线安装（需要 server 先跑起来）
  python scripts/install_builtin_packs.py

  # 指定安装目录
  python scripts/install_builtin_packs.py --offline --packs-dir /data/agentpacks
""",
    )
    parser.add_argument(
        "--offline", action="store_true",
        help="直接写入 agentpacks_dir，不需要 server 运行（推荐）",
    )
    parser.add_argument(
        "--packs-dir", default="",
        help="安装目标目录（默认：从 ~/.agentpaas/config.json 推断）",
    )
    parser.add_argument(
        "--url", default="http://127.0.0.1:8000",
        help="Server URL（在线模式，默认 http://127.0.0.1:8000）",
    )
    parser.add_argument(
        "--key", default="",
        help="API key（在线模式，默认从 ~/.agentpaas/config.json 读取）",
    )
    parser.add_argument(
        "--pack", action="append", dest="packs",
        help="只安装指定 pack（可多次指定，默认全部三个）",
    )
    args = parser.parse_args()

    packs = args.packs or BUILTIN_PACKS
    print(f"内置 Pack 源目录: {PACKS_SRC}")

    if args.offline:
        packs_dir = args.packs_dir or _default_packs_dir()
        install_offline(packs_dir, packs)
    else:
        # 读取 api_key
        api_key = args.key
        if not api_key:
            cfg = Path.home() / ".agentpaas" / "config.json"
            try:
                api_key = (json.load(open(cfg)) or {}).get("api_key", "")
            except Exception:
                pass
        install_online(args.url, api_key, packs)

    print('\n完成。在 webui 的"智能体包"页面可以看到已安装的 pack，点击"创建智能体"即可使用。\n')


if __name__ == "__main__":
    main()
