#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Generate self-extracting Python installer for AI multi-agent team.
Usage: python3 create_team_package.py
Output: install_team.py
"""

import base64
import os
import py_compile

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
TAR_PATH = os.path.join(SCRIPT_DIR, "multi-agent-team-pack.tar.gz")
OUTPUT_PATH = os.path.join(SCRIPT_DIR, "install_team.py")

if not os.path.exists(TAR_PATH):
    print("ERROR: multi-agent-team-pack.tar.gz not found at", TAR_PATH)
    exit(1)

# Read tar.gz data
with open(TAR_PATH, "rb") as f:
    data = f.read()

encoded = base64.b64encode(data).decode("ascii")
size_kb = len(encoded) / 1024
print("Package data: {:.0f} KB".format(size_kb))

# Build the installer script
# Using triple-quoted raw string, then format substitution for the payload
# All % characters in the installer body must be %% in the template
template = r'''#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
AI Multi-Agent Team - Self-Extracting Installer
Contains: 101 (Coordinator) + TopicMaster + ScriptMaster + ArticleMaster + PublishMaster + IntelMaster
Usage: python3 install_team.py
"""

import base64
import json
import os
import shutil
import subprocess
import sys
import tarfile
import tempfile

# ---- Embedded payload (base64-encoded tar.gz) ----
PAYLOAD = """%(payload)s"""

# ---- Colors ----
RED = '\033[0;31m'
GREEN = '\033[0;32m'
YELLOW = '\033[1;33m'
BLUE = '\033[0;34m'
NC = '\033[0m'

def log(msg):    print(GREEN + "[✓]" + NC, msg)
def warn(msg):   print(YELLOW + "[!]" + NC, msg)
def err(msg):    print(RED + "[✗]" + NC, msg)
def info(msg):   print(BLUE + "[i]" + NC, msg)


def check_environment():
    info("Checking environment...")

    if sys.version_info < (3, 7):
        err("Python version too old ({}), need >= 3.7".format(sys.version))
        sys.exit(1)
    log("Python {}.{}.{}".format(sys.version_info.major, sys.version_info.minor, sys.version_info.micro))

    if not shutil.which("openclaw"):
        err("OpenClaw not installed")
        info("Install OpenClaw first:")
        info("  curl -fsSL https://get.openclaw.ai | bash")
        info("  or: npm install -g openclaw")
        sys.exit(1)

    try:
        result = subprocess.run(["openclaw", "--version"], capture_output=True, text=True, timeout=10)
        log("OpenClaw " + result.stdout.strip())
    except Exception:
        log("OpenClaw found")

    if shutil.which("bun"):
        try:
            result = subprocess.run(["bun", "--version"], capture_output=True, text=True, timeout=10)
            log("bun " + result.stdout.strip())
        except Exception:
            pass
    else:
        warn("bun not found. Wechat publishing needs bun: curl -fsSL https://bun.sh/install | bash")


def extract_package():
    info("Extracting package...")
    tmpdir = tempfile.mkdtemp(prefix="ai-team-install-")
    raw_data = base64.b64decode(PAYLOAD)
    tarpath = os.path.join(tmpdir, "package.tar.gz")
    with open(tarpath, "wb") as f:
        f.write(raw_data)
    with tarfile.open(tarpath, "r:gz") as tar:
        tar.extractall(tmpdir)
    pack_dir = os.path.join(tmpdir, "multi-agent-team-pack")
    return pack_dir if os.path.isdir(pack_dir) else tmpdir


def install_agent_files(pack_dir):
    info("Creating agent workspace directories...")
    oc_root = os.environ.get("OPENCLAW_ROOT", os.path.expanduser("~/.openclaw"))
    agents_dir = os.path.join(oc_root, "agents")
    ws_dir = os.path.join(agents_dir, "101", "workspace")
    pkg_agents = os.path.join(pack_dir, "package", "agents")
    pkg_skills = os.path.join(pack_dir, "package", "skills")
    pkg_refs = os.path.join(pack_dir, "package", "references")
    pkg_baoyu = os.path.join(pack_dir, "baoyu-post-to-wechat")

    agent_names = ["101", "TopicMaster", "ScriptMaster", "ArticleMaster",
                   "PublishMaster", "IntelMaster"]
    # Map simplified names to Chinese names in files
    agent_map = {
        "101": "101",
        "TopicMaster": "\u9009\u9898\u5927\u5e08",
        "ScriptMaster": "\u811a\u672c\u5927\u5e08",
        "ArticleMaster": "\u6587\u7ae0\u5927\u5e08",
        "PublishMaster": "\u53d1\u5e03\u5927\u5e08",
        "IntelMaster": "\u60c5\u62a5\u5927\u5e08",
    }

    for agent in agent_names:
        os.makedirs(os.path.join(agents_dir, agent_map[agent], "workspace"), exist_ok=True)

    # Copy SOUL.md for each agent
    for agent in agent_names:
        ch_name = agent_map[agent]
        src = os.path.join(pkg_agents, ch_name, "workspace", "SOUL.md")
        dst = os.path.join(agents_dir, ch_name, "workspace", "SOUL.md")
        if os.path.isfile(src):
            shutil.copy2(src, dst)
            log("Installed: " + ch_name + "/SOUL.md")

    # Copy 101 extra files
    for fname in ["AGENTS.md", "MEMORY.md", "HEARTBEAT.md", "IDENTITY.md", "TOOLS.md", "USER.md"]:
        src = os.path.join(pkg_agents, "101", "workspace", fname)
        dst = os.path.join(ws_dir, fname)
        if os.path.isfile(src):
            shutil.copy2(src, dst)
            log("Installed: 101/workspace/" + fname)

    # Copy memory directory
    mem_src = os.path.join(pkg_agents, "101", "workspace", "memory")
    mem_dst = os.path.join(ws_dir, "memory")
    if os.path.isdir(mem_src):
        os.makedirs(mem_dst, exist_ok=True)
        for fname in os.listdir(mem_src):
            fp = os.path.join(mem_src, fname)
            if os.path.isfile(fp):
                shutil.copy2(fp, os.path.join(mem_dst, fname))
        log("Installed: 101/workspace/memory/")

    # Copy config templates
    cfg_src = os.path.join(pkg_agents, "101", "workspace", "config")
    cfg_dst = os.path.join(ws_dir, "config")
    if os.path.isdir(cfg_src):
        os.makedirs(cfg_dst, exist_ok=True)
        for fname in os.listdir(cfg_src):
            fp = os.path.join(cfg_src, fname)
            if os.path.isfile(fp):
                shutil.copy2(fp, os.path.join(cfg_dst, fname))
        log("Installed: config/")

    # Payment config
    pay_src = os.path.join(pkg_agents, "101", "workspace", "payment-gate-config.json")
    pay_dst = os.path.join(ws_dir, "payment-gate-config.json")
    if os.path.isfile(pay_src) and not os.path.isfile(pay_dst):
        shutil.copy2(pay_src, pay_dst)
        log("Created: payment-gate-config.json")
    elif os.path.isfile(pay_dst):
        log("Skipped: payment-gate-config.json (exists)")

    # Copy skills
    if os.path.isdir(pkg_skills):
        sk_dst = os.path.join(ws_dir, "skills")
        os.makedirs(sk_dst, exist_ok=True)
        for item in os.listdir(pkg_skills):
            s = os.path.join(pkg_skills, item)
            d = os.path.join(sk_dst, item)
            if os.path.isdir(s):
                if os.path.exists(d):
                    shutil.rmtree(d)
                shutil.copytree(s, d)
            elif os.path.isfile(s):
                shutil.copy2(s, d)
        log("Installed: skills/")

    # Copy references
    if os.path.isdir(pkg_refs):
        ref_dst = os.path.join(ws_dir, "references")
        os.makedirs(ref_dst, exist_ok=True)
        for item in os.listdir(pkg_refs):
            s = os.path.join(pkg_refs, item)
            d = os.path.join(ref_dst, item)
            if os.path.isdir(s):
                if os.path.exists(d):
                    shutil.rmtree(d)
                shutil.copytree(s, d)
            elif os.path.isfile(s):
                shutil.copy2(s, d)
        log("Installed: references/")

    # PublishMaster scripts
    pubmaps = os.path.join(pkg_agents, agent_map["PublishMaster"], "workspace", "scripts")
    pubmapd = os.path.join(agents_dir, agent_map["PublishMaster"], "workspace", "scripts")
    if os.path.isdir(pubmaps):
        os.makedirs(pubmapd, exist_ok=True)
        for fname in os.listdir(pubmaps):
            fs = os.path.join(pubmaps, fname)
            fd = os.path.join(pubmapd, fname)
            if os.path.isfile(fs):
                shutil.copy2(fs, fd)
        log("Installed: PublishMaster/scripts/")

    # Z-Blog publisher
    zblog_src = os.path.join(pkg_agents, agent_map["PublishMaster"], "workspace",
                             "openclaw-zblog-markdown-publisher")
    zblog_dst = os.path.join(agents_dir, agent_map["PublishMaster"], "workspace",
                             "openclaw-zblog-markdown-publisher")
    if os.path.isdir(zblog_src):
        if os.path.exists(zblog_dst):
            shutil.rmtree(zblog_dst)
        shutil.copytree(zblog_src, zblog_dst)
        log("Installed: Z-Blog publisher")

    # Baoyu EXTEND.md
    ext_src = os.path.join(pkg_baoyu, "EXTEND.md")
    ext_dir = os.path.expanduser("~/.baoyu-skills/baoyu-post-to-wechat")
    os.makedirs(ext_dir, exist_ok=True)
    ext_dst = os.path.join(ext_dir, "EXTEND.md")
    if os.path.isfile(ext_src) and not os.path.isfile(ext_dst):
        shutil.copy2(ext_src, ext_dst)
        log("Created: wechat config template")
        warn("Please edit ~/.baoyu-skills/baoyu-post-to-wechat/EXTEND.md with your real AppID/AppSecret")

    return ws_dir


def install_dependencies(ws_dir):
    info("Installing dependencies...")
    wc_dir = os.path.join(ws_dir, "skills", "baoyu-post-to-wechat", "scripts")
    if os.path.isfile(os.path.join(wc_dir, "package.json")):
        info("Installing wechat publishing dependencies...")
        try:
            if shutil.which("bun"):
                subprocess.run(["bun", "install", "--production", "--silent"], cwd=wc_dir, timeout=120)
            else:
                subprocess.run(["npm", "install", "--production", "--silent"], cwd=wc_dir, timeout=120)
            log("Wechat dependencies installed")
        except Exception as e:
            warn("Wechat dep install failed: " + str(e))

    agents_dir = os.path.dirname(os.path.dirname(ws_dir))
    zblog_dir = os.path.join(agents_dir, "\u53d1\u5e03\u5927\u5e08", "workspace",
                             "openclaw-zblog-markdown-publisher")
    if os.path.isfile(os.path.join(zblog_dir, "package.json")):
        info("Installing publish dependencies...")
        try:
            subprocess.run(["npm", "install", "--production", "--silent"], cwd=zblog_dir, timeout=120)
            log("Publish dependencies installed")
        except Exception as e:
            warn("Publish dep install failed: " + str(e))


def show_hints(ws_dir):
    print()
    info("First-time setup - edit these files:")
    print()
    info("  Wechat Official Account:")
    info("    ~/.baoyu-skills/baoyu-post-to-wechat/EXTEND.md")
    info("  Website publishing:")
    info("    " + ws_dir + "/config/sites.yaml")
    info("  Jin10 financial data:")
    info("    " + ws_dir + "/config/jin10-token")
    info("  Alipay payment:")
    info("    " + ws_dir + "/config/payment.yaml")
    info("  Payment plugin:")
    info("    npm install -g @alipay/alipay-agent-payment")
    info("    alipay-bot apply-wallet --agent-name \"101\"")
    print()


def register_agents():
    info("Registering agents with OpenClaw...")
    oc_root = os.environ.get("OPENCLAW_ROOT", os.path.expanduser("~/.openclaw"))
    agents_dir = os.path.join(oc_root, "agents")
    oc_json = os.path.join(oc_root, "openclaw.json")
    agents_to_register = ["\u9009\u9898\u5927\u5e08", "\u811a\u672c\u5927\u5e08",
                          "\u6587\u7ae0\u5927\u5e08", "\u53d1\u5e03\u5927\u5e08",
                          "\u60c5\u62a5\u5927\u5e08"]
    registered = set()
    if os.path.isfile(oc_json):
        try:
            with open(oc_json) as f:
                cfg = json.load(f)
            for a in cfg.get("agents", {}).get("list", []):
                registered.add(a.get("id", ""))
        except Exception:
            pass
    for agent in agents_to_register:
        if agent in registered:
            log(agent + " already registered (skip)")
            continue
        info("Registering " + agent + "...")
        ws = os.path.join(agents_dir, agent, "workspace")
        if not os.path.isdir(ws):
            warn(agent + " workspace not found: " + ws)
            continue
        try:
            subprocess.run(["openclaw", "agents", "register", agent,
                           "--workspace", ws, "--model", "deepseek/deepseek-chat"],
                           timeout=30, check=True)
            log(agent + " registered")
        except subprocess.CalledProcessError:
            warn(agent + " registration failed, you can manually register later")
        except Exception as e:
            warn(agent + " registration error: " + str(e))


def main():
    print()
    print("=" * 54)
    print("   AI Multi-Agent Team - One-Click Install")
    print("   101 + TopicMaster + ScriptMaster + ArticleMaster")
    print("   + PublishMaster + IntelMaster")
    print("=" * 54)
    print()

    check_environment()
    print()
    pack_dir = extract_package()
    log("Extracted to: " + pack_dir)
    ws_dir = install_agent_files(pack_dir)
    print()
    install_dependencies(ws_dir)
    print()
    register_agents()
    print()
    show_hints(ws_dir)

    # Cleanup temp
    parent = os.path.dirname(pack_dir)
    if parent and os.path.isdir(parent):
        shutil.rmtree(parent, ignore_errors=True)

    print()
    print("=" * 54)
    print("           INSTALLATION COMPLETE!")
    print("=" * 54)
    print("  1. Restart OpenClaw:")
    print("     openclaw gateway restart")
    print()
    print("  2. Verify agents:")
    print("     openclaw agents list")
    print()
    print("  3. View agent SOUL.md files:")
    print("     ls ~/.openclaw/agents/*/workspace/SOUL.md")
    print("=" * 54)
    print()
    log("Installation complete!")


if __name__ == "__main__":
    main()
''' % {"payload": encoded}

with open(OUTPUT_PATH, "w", encoding="utf-8") as f:
    f.write(template)

os.chmod(OUTPUT_PATH, 0o755)
final_size = os.path.getsize(OUTPUT_PATH)
print("Installer generated: " + OUTPUT_PATH)
print("Size: {:.0f} KB".format(final_size / 1024))
print("Usage: python3 " + OUTPUT_PATH)
print()

# Syntax check
print("Verifying syntax...")
try:
    py_compile.compile(OUTPUT_PATH, doraise=True)
    print("  Syntax OK")
except py_compile.PyCompileError as e:
    print("  Syntax error:", e)
    exit(1)

# Verify payload
print("Verifying payload...")
decoded = base64.b64decode(encoded)
assert len(decoded) == len(data), "Data length mismatch"
print("  Payload OK ({} bytes raw -> {} bytes encoded)".format(len(data), len(encoded)))
print()
print("ALL CHECKS PASSED")
