/**
 * ClawAdapter — PR-26
 *
 * 将 Claw 数据结构（memory/blocs/, memory/cycles/, memory/candidates/）
 * 映射到统一 Agent Contract。
 *
 * 不修改 PR-13~25 核心逻辑，仅作为抽象层运行。
 *
 * Usage:
 *   import { ClawAdapter } from "./src/agent-adapters/claw-adapter.mjs";
 *   const adapter = new ClawAdapter();
 *   const contract = adapter.normalize({ basePath: "..." });
 *
 * @module claw-adapter
 */

import { AgentAdapter } from "./agent-adapter.mjs";
import { readdirSync, statSync, readFileSync, existsSync } from "node:fs";
import { resolve } from "node:path";

// Claw 的目录结构（支持多种命名约定）
const CLAW_DIRS = [
  "memory/blocs",      // 标准命名
  "memory/core",       // 实际工作区使用
  "memory/cycles",     // 标准命名
  "memory/daily",      // 实际工作区使用
  "memory/candidates", // 标准命名
];

/**
 * Claw 数据结构 Adapter
 */
export class ClawAdapter extends AgentAdapter {
  getAgentType() {
    return "claw";
  }

  /**
   * 检测 source 是否为 Claw 数据结构。
   *
   * @param {object|string} source — { basePath } 或路径字符串
   * @returns {boolean}
   */
  detect(source) {
    const basePath = typeof source === "string" ? source : source?.basePath;
    if (!basePath) return false;

    // 检查 Claw 目录结构
    const dirsPresent = CLAW_DIRS.filter(dir => existsSync(resolve(basePath, dir)));
    return dirsPresent.length >= 2; // 至少 2/3 核心目录存在
  }

  /**
   * 从 Claw 数据结构提取指标，映射到统一 Contract。
   *
   * @param {object|string} source — { basePath } 或路径字符串
   * @returns {object} — 符合 AgentContract 格式
   */
  normalize(source) {
    const basePath = typeof source === "string" ? source : source?.basePath;
    if (!basePath) {
      return this._makeContract({ memoryUnits: 0, activeUnits: 0, archivedUnits: 0, groups: 0 });
    }

    // 提取 Claw 指标的辅助函数
    const countMdFiles = (dir) => {
      try {
        return readdirSync(dir, { withFileTypes: true })
          .filter(e => e.isFile() && e.name.endsWith(".md"))
          .length;
      } catch { return 0; }
    };

    const walkMdFiles = (dir) => {
      const files = [];
      try {
        const walk = (d) => {
          for (const entry of readdirSync(d, { withFileTypes: true })) {
            const full = resolve(d, entry.name);
            if (entry.isFile() && entry.name.endsWith(".md")) files.push(full);
            else if (entry.isDirectory() && !entry.name.startsWith(".")) walk(full);
          }
        };
        walk(dir);
      } catch { /* skip */ }
      return files;
    };

    const memoryDir = resolve(basePath, "memory");

    // groups = memory/blocs 或 memory/core 中的 .md 文件数
    const blocsDir = existsSync(resolve(memoryDir, "blocs"))
      ? resolve(memoryDir, "blocs")
      : resolve(memoryDir, "core");
    const groups = countMdFiles(blocsDir);

    // memoryUnits = memory 下所有 .md 文件
    const allMd = walkMdFiles(memoryDir);
    const memoryUnits = allMd.length;

    // activeUnits = 排除 daily/ 和系统目录的 .md 文件
    const activeUnits = allMd.filter(f =>
      !f.includes("/daily/") &&
      !f.includes("/backups/") &&
      !f.includes("/.auto") &&
      !f.includes("/.session")
    ).length;

    // archivedUnits = 在 daily/、backups/ 或 archives/ 目录下的文件
    const archivedUnits = allMd.filter(f =>
      f.includes("/daily/") ||
      f.includes("/backups/") ||
      f.includes("/archives/")
    ).length;

    return this._makeContract({
      memoryUnits,
      activeUnits,
      archivedUnits,
      groups,
      sourceVersion: "1.0.x",
      adapterVersion: "1.0.0",
    });
  }
}
