#!/usr/bin/env node

/**
 * switch-agent.mjs — Switch the active cc-connect agent.
 *
 * Usage:
 *   node scripts/switch-agent.mjs <agent>     # Switch to agent (codex, claudecode, gemini)
 *   node scripts/switch-agent.mjs --status    # Show current active agent
 *
 * Strategy:
 *   1. Try HTTP API (dev server has write permissions to ~/.cc-connect/)
 *   2. Fall back to direct file manipulation if HTTP fails
 */

import fs from 'fs';
import path from 'path';
import os from 'os';
import { execSync } from 'child_process';

const SUPPORTED_AGENTS = ['codex', 'claudecode', 'gemini'];
const ALIASES = { claude: 'claudecode', cc: 'claudecode', gem: 'gemini', cx: 'codex' };

// Read dev server info to get the port
function getDevServerPort() {
  const candidates = [
    path.join(process.cwd(), '.axhub', 'make', '.dev-server-info.json'),
    path.resolve(import.meta.dirname, '..', '.axhub', 'make', '.dev-server-info.json'),
  ];
  for (const p of candidates) {
    try {
      const info = JSON.parse(fs.readFileSync(p, 'utf8'));
      if (info?.port) return info.port;
    } catch { /* ignore */ }
  }
  return 51720; // default
}

// ---------------------------------------------------------------------------
// HTTP-based switching (preferred — dev server has write permissions)
// ---------------------------------------------------------------------------

async function httpSwitch(target) {
  const port = getDevServerPort();
  const url = `http://127.0.0.1:${port}/api/cc-connect/switch-agent`;
  const res = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ agent: target }),
    signal: AbortSignal.timeout(15000),
  });
  const data = await res.json();
  if (data.success) {
    return { ok: true, detail: data.message || `已切换到 ${target}` };
  }
  return { ok: false, detail: data.error || '切换失败' };
}

async function httpStatus() {
  const port = getDevServerPort();
  const url = `http://127.0.0.1:${port}/api/cc-connect/active-agent`;
  const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
  return await res.json();
}

// ---------------------------------------------------------------------------
// File-based switching (fallback — requires write permissions to ~/.cc-connect/)
// ---------------------------------------------------------------------------

const CC_CONNECT_DIR = path.join(os.homedir(), '.cc-connect');
const STATE_PATH = path.join(CC_CONNECT_DIR, 'axhub-weixin-state.json');
const CONFIG_PATH = path.join(CC_CONNECT_DIR, 'config.toml');

function readState() {
  if (!fs.existsSync(STATE_PATH)) return null;
  try {
    const parsed = JSON.parse(fs.readFileSync(STATE_PATH, 'utf8'));
    if (parsed?.version === 1 && parsed?.activeAgent && parsed?.weixinOptions?.token) {
      return parsed;
    }
  } catch { /* ignore */ }
  return null;
}

function escapeToml(value) {
  return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\t/g, '\\t');
}

function fileSwitch(target) {
  const state = readState();
  if (!state) {
    return { ok: false, detail: '未找到微信绑定状态，请先在管理后台扫码绑定' };
  }
  if (state.activeAgent === target) {
    return { ok: true, detail: `当前已是 ${target}，无需切换` };
  }

  state.activeAgent = target;
  fs.mkdirSync(CC_CONNECT_DIR, { recursive: true });
  fs.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2), 'utf8');

  const optionLines = Object.entries(state.weixinOptions)
    .map(([k, v]) => `${k} = "${escapeToml(String(v))}"`)
    .join('\n');

  const config = `# Auto-generated by Axhub Make
# language = "zh"

[log]
level = "info"

[[projects]]
name = "axhub-${escapeToml(target)}"

[projects.agent]
type = "${escapeToml(target)}"

[projects.agent.options]
work_dir = "${escapeToml(state.workDir)}"
mode = "yolo"

[[projects.platforms]]
type = "weixin"

[projects.platforms.options]
${optionLines}
`;

  fs.writeFileSync(CONFIG_PATH, config, 'utf8');

  const ccCommand = process.platform === 'win32' ? 'cc-connect.cmd' : 'cc-connect';
  try { execSync(`${ccCommand} daemon stop`, { stdio: 'ignore', timeout: 10000 }); } catch { /* */ }
  try { execSync(`${ccCommand} daemon uninstall`, { stdio: 'ignore', timeout: 10000 }); } catch { /* */ }
  try {
    execSync(`${ccCommand} daemon install --config "${CONFIG_PATH}"`, { stdio: 'inherit', timeout: 20000 });
    return { ok: true, detail: `已切换到 ${target}` };
  } catch (error) {
    return { ok: false, detail: `配置已更新，但 daemon 重启失败: ${error.message}` };
  }
}

function fileStatus() {
  const state = readState();
  if (state) {
    return { activeAgent: state.activeAgent, configuredAgents: state.configuredAgents };
  }
  return null;
}

// ---------------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------------

const args = process.argv.slice(2);

if (args.length === 0 || args[0] === '--help') {
  console.log('用法: node scripts/switch-agent.mjs <agent>');
  console.log(`可用: ${SUPPORTED_AGENTS.join(', ')}`);
  console.log('别名: claude→claudecode, gem→gemini, cx→codex');
  console.log('      node scripts/switch-agent.mjs --status');
  process.exit(0);
}

if (args[0] === '--status') {
  const data = fileStatus();
  if (data) {
    console.log(JSON.stringify(data, null, 2));
  } else {
    try {
      const httpData = await httpStatus();
      console.log(JSON.stringify(httpData, null, 2));
    } catch {
      console.log('未找到微信绑定状态');
    }
  }
  process.exit(0);
}

let target = args[0].toLowerCase();
if (ALIASES[target]) target = ALIASES[target];

if (!SUPPORTED_AGENTS.includes(target)) {
  console.error(`❌ 不支持的 agent: ${target}`);
  console.error(`可用: ${SUPPORTED_AGENTS.join(', ')}`);
  process.exit(1);
}

// Strategy: try file-based first, fall back to HTTP API
try {
  const result = fileSwitch(target);
  if (result.ok) {
    console.log(`✅ ${result.detail}`);
    process.exit(0);
  } else {
    console.error(`❌ 本地切换失败: ${result.detail}`);
    console.log('尝试 HTTP API 切换...');
  }
} catch (fileError) {
  console.log(`本地文件操作受限 (${fileError.message})，尝试 HTTP API 切换...`);
}

// Fallback to HTTP API
try {
  const result = await httpSwitch(target);
  if (result.ok) {
    console.log(`✅ ${result.detail}`);
  } else {
    console.error(`❌ ${result.detail}`);
    process.exit(1);
  }
} catch (httpError) {
  console.error(`❌ HTTP API 也不可达: ${httpError.message}`);
  console.error('请在管理后台的微信连接对话框中进行切换');
  process.exit(1);
}
