/**
 * AgentAdapter — PR-26 抽象基类
 *
 * 定义所有 Agent Adapter 必须实现的接口：
 *   getAgentType()  — 返回 Agent 类型标识
 *   detect(source)   — 检测 source 是否适用此 Adapter
 *   normalize(source) — 将 Agent 数据映射到统一 Contract
 *   validate(contract) — 验证 Contract 字段完整性
 *
 * 纯接口层，无第三方依赖，无副作用。
 *
 * @module agent-adapter
 */

/**
 * @typedef {object} AgentContract
 * @property {string} schemaVersion  — Contract schema 版本号
 * @property {string} agentType      — Agent 类型标识
 * @property {object} metrics        — 指标数据
 * @property {number} metrics.memoryUnits    — 总记忆/知识单元数
 * @property {number} metrics.activeUnits    — 活跃单元数
 * @property {number} metrics.archivedUnits  — 已归档单元数
 * @property {number} metrics.groups         — 分组/上下文数
 * @property {object} [metadata]            — 可选元数据
 * @property {string} [metadata.sourceVersion]   — Agent 原始版本
 * @property {string} [metadata.adapterVersion]  — Adapter 版本
 */

export class AgentAdapter {
  /**
   * @returns {string} Agent 类型标识
   */
  getAgentType() {
    throw new Error("getAgentType() must be implemented by subclass");
  }

  /**
   * 检测 source 是否属于此 Adapter。
   *
   * @param {object|string} source — Agent 原始数据结构或 path
   * @returns {boolean} — true 表示可处理
   */
  detect(source) {
    throw new Error("detect() must be implemented by subclass");
  }

  /**
   * 将 Agent 原始数据映射到统一 Contract。
   *
   * @param {object|string} source — Agent 原始数据结构或 path
   * @returns {AgentContract} — 符合统一 Contract 的对象
   */
  normalize(source) {
    throw new Error("normalize() must be implemented by subclass");
  }

  /**
   * 验证 Contract 字段完整性。
   * 纯函数，无副作用。
   *
   * @param {AgentContract} contract
   * @returns {{ valid: boolean, errors: string[], warnings: string[] }}
   */
  validate(contract) {
    const errors = [];
    const warnings = [];

    if (!contract || typeof contract !== "object") {
      return { valid: false, errors: ["Contract must be a non-null object"], warnings: [] };
    }

    // schemaVersion
    if (typeof contract.schemaVersion !== "string" || contract.schemaVersion.length === 0) {
      errors.push("schemaVersion must be a non-empty string");
    } else {
      const parts = contract.schemaVersion.split(".");
      if (parts.length !== 2 || isNaN(parseInt(parts[0], 10)) || isNaN(parseInt(parts[1], 10))) {
        errors.push(`schemaVersion "${contract.schemaVersion}" must follow "major.minor" format`);
      }
    }

    // agentType
    if (typeof contract.agentType !== "string" || contract.agentType.length === 0) {
      errors.push("agentType must be a non-empty string");
    }

    // metrics
    if (!contract.metrics || typeof contract.metrics !== "object") {
      errors.push("metrics must be an object");
    } else {
      const requiredMetrics = ["memoryUnits", "activeUnits", "archivedUnits", "groups"];
      for (const m of requiredMetrics) {
        if (typeof contract.metrics[m] !== "number" || !Number.isInteger(contract.metrics[m]) || contract.metrics[m] < 0) {
          errors.push(`metrics.${m} must be a non-negative integer`);
        }
      }

      // Invariant: activeUnits + archivedUnits <= memoryUnits
      if (typeof contract.metrics.activeUnits === "number" &&
          typeof contract.metrics.archivedUnits === "number" &&
          typeof contract.metrics.memoryUnits === "number") {
        if (contract.metrics.activeUnits + contract.metrics.archivedUnits > contract.metrics.memoryUnits) {
          warnings.push("activeUnits + archivedUnits exceeds memoryUnits");
        }
      }
    }

    return { valid: errors.length === 0, errors, warnings };
  }

  /**
   * 创建一个标准的 AgentContract 对象。
   *
   * @param {object} fields
   * @returns {AgentContract}
   */
  _makeContract(fields = {}) {
    return {
      schemaVersion: "1.0",
      agentType: this.getAgentType(),
      metrics: {
        memoryUnits: fields.memoryUnits ?? 0,
        activeUnits: fields.activeUnits ?? 0,
        archivedUnits: fields.archivedUnits ?? 0,
        groups: fields.groups ?? 0,
      },
      metadata: {
        sourceVersion: fields.sourceVersion ?? "",
        adapterVersion: fields.adapterVersion ?? "1.0.0",
      },
    };
  }
}
