/**
 * ============================================================================
 * MyClaw Pull - 从 ~/.openclaw/ 拉取最新资源到 myclaw 源目录
 * ============================================================================
 * 
 * 反向同步：将线上运行环境中的智能体、技能拷贝回 myclaw 包内，
 * 确保下次 publish 时打包的是最新版本。
 * 
 * 拉取范围：
 *   1. manifest 中已有的 agents → 从 ~/.openclaw/workspace-* 回拷到 agent-list/
 *   2. manifest 中已有的 skills → 从 ~/.openclaw/skills/* 回拷到 skills/
 *   3. 如果发现 ~/.openclaw/ 中有新的 workspace-* 不在 manifest 中，提示是否纳入
 * 
 * ============================================================================
 */

const fs = require('fs');
const path = require('path');
const os = require('os');

const OPENCLAW_DIR = path.join(os.homedir(), '.openclaw');
const AGENT_LIST_DIR = path.join(__dirname, 'agent-list');
const SKILLS_DIR = path.join(__dirname, 'skills');
const MANIFEST_PATH = path.join(__dirname, 'patches/patch-manifest.json');

// 不应拉取的 workspace（排除列表）
const WORKSPACE_IGNORE = new Set([
  'workspace',           // 默认 workspace（非 agent）
]);

/**
 * 递归复制目录（幂等覆盖）
 * 跳过 .openclaw/ 和 node_modules/ 等运行时目录
 */
function copyDirSync(src, dest, skipDirs = ['.openclaw', 'node_modules', '.git']) {
  if (!fs.existsSync(dest)) {
    fs.mkdirSync(dest, { recursive: true });
  }

  const entries = fs.readdirSync(src, { withFileTypes: true });
  for (const entry of entries) {
    if (skipDirs.includes(entry.name)) continue;

    const srcPath = path.join(src, entry.name);
    const destPath = path.join(dest, entry.name);

    if (entry.isDirectory()) {
      copyDirSync(srcPath, destPath, skipDirs);
    } else {
      fs.copyFileSync(srcPath, destPath);
    }
  }
}

/**
 * 统计目录内文件数量
 */
function countFiles(dir) {
  if (!fs.existsSync(dir)) return 0;
  let count = 0;
  const entries = fs.readdirSync(dir, { withFileTypes: true });
  for (const e of entries) {
    if (e.isDirectory()) {
      count += countFiles(path.join(dir, e.name));
    } else {
      count++;
    }
  }
  return count;
}

/**
 * 加载 manifest
 */
function loadManifest() {
  if (!fs.existsSync(MANIFEST_PATH)) return null;
  try {
    return JSON.parse(fs.readFileSync(MANIFEST_PATH, 'utf8'));
  } catch { return null; }
}

/**
 * 扫描 ~/.openclaw/ 下所有 workspace-* 目录
 */
function scanLiveWorkspaces() {
  if (!fs.existsSync(OPENCLAW_DIR)) return [];
  return fs.readdirSync(OPENCLAW_DIR, { withFileTypes: true })
    .filter(d => d.isDirectory() && d.name.startsWith('workspace-') && !WORKSPACE_IGNORE.has(d.name))
    .map(d => ({
      dirName: d.name,
      id: d.name.replace(/^workspace-/, ''),
      fullPath: path.join(OPENCLAW_DIR, d.name),
    }))
    .filter(ws => !AGENT_LIST_DIR.startsWith(ws.fullPath)); // 避免无限递归（比如拉取源码所在的 workspace）
}

/**
 * 扫描 ~/.openclaw/skills/ 下所有技能目录
 */
function scanLiveSkills() {
  const skillsDir = path.join(OPENCLAW_DIR, 'skills');
  if (!fs.existsSync(skillsDir)) return [];
  return fs.readdirSync(skillsDir, { withFileTypes: true })
    .filter(d => d.isDirectory())
    .map(d => ({
      name: d.name,
      fullPath: path.join(skillsDir, d.name),
      hasSkillMd: fs.existsSync(path.join(skillsDir, d.name, 'SKILL.md')),
    }));
}

/**
 * 执行拉取
 */
function run() {
  const bar = '----------------------------------------';

  console.log('');
  console.log('[\x1b[34mMyClaw\x1b[0m] \x1b[34mPull - 拉取最新资源\x1b[0m');
  console.log(bar);
  console.log('');

  if (!fs.existsSync(OPENCLAW_DIR)) {
    console.log('[\x1b[31m错误\x1b[0m] ~/.openclaw 目录不存在');
    return;
  }

  // 确保目标目录存在
  if (!fs.existsSync(AGENT_LIST_DIR)) {
    fs.mkdirSync(AGENT_LIST_DIR, { recursive: true });
  }

  const manifest = loadManifest();
  const manifestAgentIds = new Set();
  const manifestSkillNames = new Set();

  if (manifest) {
    if (manifest.agents) manifest.agents.forEach(a => manifestAgentIds.add(a.id));
    if (manifest.skills) manifest.skills.forEach(s => manifestSkillNames.add(s.name));
  }

  // === 1. 拉取智能体 ===
  console.log('\x1b[34m🤖 智能体 (Agents)\x1b[0m');

  const liveWorkspaces = scanLiveWorkspaces();
  let agentPulled = 0;
  for (const ws of liveWorkspaces) {
    const destDir = path.join(AGENT_LIST_DIR, ws.dirName);
    const inManifest = manifestAgentIds.has(ws.id);

    if (inManifest) {
      const fileCount = countFiles(ws.fullPath);
      copyDirSync(ws.fullPath, destDir);
      console.log('  🔄 已同步: ' + ws.id + ' (' + fileCount + ' 文件)');
      agentPulled++;
    }
  }

  if (agentPulled === 0) {
    console.log('  (没有需要同步的智能体)');
  }

  // === 2. 拉取技能 ===
  console.log('');
  console.log('\x1b[34m🧩 技能 (Skills)\x1b[0m');

  const liveSkills = scanLiveSkills();
  let skillPulled = 0;

  for (const sk of liveSkills) {
    const inManifest = manifestSkillNames.has(sk.name);

    if (inManifest) {
      if (!sk.hasSkillMd) {
        console.log('  ⚠️ 跳过无 SKILL.md 的技能: ' + sk.name);
        continue;
      }
      const destDir = path.join(SKILLS_DIR, sk.name);
      const fileCount = countFiles(sk.fullPath);
      copyDirSync(sk.fullPath, destDir);
      console.log('  🔄 已同步: ' + sk.name + ' (' + fileCount + ' 文件)');
      skillPulled++;
    }
  }

  if (skillPulled === 0) {
    console.log('  (没有需要同步的技能)');
  }

  // === 汇总 ===
  console.log('');
  console.log(bar);
  console.log('✅ Pull 完毕: 同步了 ' + agentPulled + ' 个智能体, ' + skillPulled + ' 个技能');
  console.log('');
}

module.exports = { run };
