#!/usr/bin/env python3
"""
统一换绑工具 — 从 session URL 自动解析参数，调用底层脚本。

用法:
  # 场景1: 彻底清空
  python3 rebind.py --url <URL> --action full-reset --yes

  # 场景2: 新账号绑定（无 URL，手动填）
  python3 rebind.py --action bind --account-id <id> --agent <agent> --yes

  # 场景3: 软性换绑
  python3 rebind.py --url <URL> --new-agent <agent> --action soft-switch --yes
"""
import argparse
import json
import subprocess
import sys
from pathlib import Path
from urllib.parse import urlparse, parse_qs, unquote

SCRIPT_DIR = Path(__file__).parent


# ── URL 解析 ──────────────────────────────────────────────

def parse_session_url(url):
    """
    从 Control UI 的 session URL 中提取所有参数。

    URL 格式:
      http://127.0.0.1:18789/chat?session=agent%3Asun%3Aopenclaw-weixin%3A...

    decode 后 session 值的格式:
      agent:<agent>:<channel>:<account_id>:direct:<peer>
    """
    parsed = urlparse(url)
    qs = parse_qs(parsed.query)
    session_raw = qs.get('session', [''])[0]
    session = unquote(session_raw)

    # agent:sun:openclaw-weixin:c68acec51e3a-im-bot:direct:o9cq...@im.wechat
    parts = session.split(':')
    if len(parts) < 6 or parts[0] != 'agent':
        print(f'❌ 无法解析 session URL: {session}')
        print(f'   期望格式: agent:<agent>:<channel>:<account_id>:direct:<peer>')
        sys.exit(1)

    result = {
        'agent': parts[1],
        'channel': parts[2],
        'account_id': parts[3],
        # parts[4] = 'direct'
        'peer': ':'.join(parts[5:]),  # peer 可能包含 ':'
    }

    print('📋 从 URL 解析出的参数:')
    print(f'   agent:      {result["agent"]}')
    print(f'   channel:    {result["channel"]}')
    print(f'   account_id: {result["account_id"]}')
    print(f'   peer:       {result["peer"]}')
    print()

    return result


# ── 底层脚本调用 ──────────────────────────────────────────

def run_script(script_name, args_list):
    """调用底层 Python 脚本"""
    script_path = SCRIPT_DIR / script_name
    cmd = [sys.executable, str(script_path)] + args_list
    print(f'🔧 执行: {" ".join(cmd)}')
    print()
    result = subprocess.run(cmd)
    return result.returncode == 0


def run_reset(channel, account_id, peer=None, restart=True, yes=False):
    """调用 reset_dm_route_state.py"""
    args = ['--channel', channel, '--account-id', account_id]
    if peer:
        args += ['--peer', peer]
    if restart:
        args.append('--restart-gateway')
    if yes:
        args.append('--yes')
    return run_script('reset_dm_route_state.py', args)


def run_bind(channel, account_id, agent, restart=True, yes=False):
    """调用 bind_dm_route.py"""
    args = ['--channel', channel, '--account-id', account_id, '--agent', agent]
    if restart:
        args.append('--restart-gateway')
    if yes:
        args.append('--yes')
    return run_script('bind_dm_route.py', args)


# ── 三个场景 ──────────────────────────────────────────────

def action_full_reset(info, yes):
    """场景1: 彻底清空"""
    print('🔄 场景1: 彻底清空')
    print(f'   将清除账号 {info["account_id"]} 的所有状态')
    print()
    return run_reset(info['channel'], info['account_id'], restart=True, yes=yes)


def action_bind(channel, account_id, agent, yes):
    """场景2: 新账号绑定"""
    print('🆕 场景2: 新账号绑定')
    print(f'   {account_id} → {agent}')
    print()
    return run_bind(channel, account_id, agent, restart=True, yes=yes)


def action_soft_switch(info, new_agent, yes):
    """场景3: 软性换绑"""
    print('🔀 场景3: 软性换绑')
    print(f'   {info["account_id"]}: {info["agent"]} → {new_agent}')
    print()

    # 第1步: 写新 binding
    print('── 步骤 1/3: 写入新 binding ──')
    ok = run_bind(info['channel'], info['account_id'], new_agent, restart=False, yes=yes)
    if not ok:
        print('❌ 写入 binding 失败')
        return False

    # 第2步: 清旧 session（--peer 软清）
    print()
    print('── 步骤 2/3: 清除旧 session ──')
    ok = run_reset(info['channel'], info['account_id'], peer=info['peer'], yes=yes)
    if not ok:
        print('❌ 清除 session 失败')
        return False

    # 第3步: 重启 gateway
    print()
    print('── 步骤 3/3: 重启 Gateway ──')
    result = subprocess.run(['openclaw', 'gateway', 'restart'], capture_output=True, text=True)
    if result.returncode == 0:
        print('✅ Gateway 重启成功')
    else:
        print(f'⚠️  Gateway 重启返回码: {result.returncode}')
        if result.stderr:
            print(f'   {result.stderr.strip()}')

    return True


# ── 主入口 ────────────────────────────────────────────────

def main():
    ap = argparse.ArgumentParser(
        description='统一换绑工具 — 从 session URL 自动解析参数',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog='''
场景示例:
  彻底清空:   python3 rebind.py --url <URL> --action full-reset --yes
  新账号绑定: python3 rebind.py --action bind --account-id <id> --agent <agent> --yes
  软性换绑:   python3 rebind.py --url <URL> --new-agent <agent> --action soft-switch --yes
        ''')
    ap.add_argument('--url', help='Control UI 的 session URL（自动解析参数）')
    ap.add_argument('--action', required=True, choices=['full-reset', 'bind', 'soft-switch'])
    ap.add_argument('--new-agent', help='软性换绑时的目标 Agent')
    ap.add_argument('--account-id', help='手动指定 accountId（场景2 无 URL 时使用）')
    ap.add_argument('--agent', help='手动指定 Agent（场景2 无 URL 时使用）')
    ap.add_argument('--channel', default='openclaw-weixin')
    ap.add_argument('--yes', action='store_true', help='跳过确认')
    ap.add_argument('--dry-run', action='store_true', help='只预览不执行')
    args = ap.parse_args()

    if args.dry_run:
        args.yes = False  # dry-run 隐含不 --yes

    info = None
    if args.url:
        info = parse_session_url(args.url)

    if args.action == 'full-reset':
        if not info:
            ap.error('场景1 需要 --url 参数')
        ok = action_full_reset(info, yes=args.yes and not args.dry_run)
        if ok:
            print()
            print('✅ 清空完成。下一步:')
            print('   1. 运行 openclaw channels login --channel openclaw-weixin 重新扫码')
            print('   2. 运行 myclaw rebind 选场景2绑定新账号')

    elif args.action == 'bind':
        account_id = args.account_id or (info and info['account_id'])
        agent = args.agent or (info and info.get('new_agent'))
        if not account_id or not agent:
            ap.error('场景2 需要 --account-id 和 --agent（或通过 --url 提供）')
        ok = action_bind(args.channel, account_id, agent, yes=args.yes and not args.dry_run)
        if ok:
            print()
            print('✅ 绑定完成。发一条测试消息验证 routing。')

    elif args.action == 'soft-switch':
        if not info:
            ap.error('场景3 需要 --url 参数')
        if not args.new_agent:
            ap.error('场景3 需要 --new-agent 参数')
        ok = action_soft_switch(info, args.new_agent, yes=args.yes and not args.dry_run)
        if ok:
            print()
            print('✅ 软性换绑完成。发一条测试消息验证新 Agent 响应。')


if __name__ == '__main__':
    main()
