#!/usr/bin/env node
/**
 * Release Candidate 检查清单 — PR-13 Active Memory Precompute RC
 *
 * 汇总 readiness、rollout stage、rollback report、circuit breaker
 * 和 test summary，判断系统是否具备 Release Candidate 条件。
 *
 * 这是一个纯函数模块，不：
 *   - 读写任何文件
 *   - 读写环境变量
 *   - 读写 SQLite / FTS5
 *   - 修改 MEMORY.md
 *   - 修改生产召回路径
 *   - 有任何副作用
 *
 * 输出状态：
 *   pass — 所有必须门禁通过，可以进入 RC
 *   warn — 存在警示但不阻塞 RC
 *   fail — 存在阻塞项，不能进入 RC
 *
 * 检查项：
 *   必须通过（blocker）：
 *     - readiness.status === "pass"
 *     - rolloutStage.action === "promote" || (currentStage === 100 && freeze)
 *     - rollbackReport.recommendation === "keep_enabled"
 *     - circuitBreaker.state === "closed"
 *     - testSummary.failed === 0
 *     - testSummary.regressions === 0
 *
 *   警告但不阻塞（warning）：
 *     - 样本量刚达标
 *     - confidence 偏低
 *     - rollout 未到 100%
 *     - readiness.score 偏低
 *
 * @module precompute-release-candidate-checklist
 */

// ─── 状态常量 ────────────────────────────────────────

export const RC_PASS = "pass";
export const RC_WARN = "warn";
export const RC_FAIL = "fail";

// ─── 默认选项 ────────────────────────────────────────

const DEFAULT_OPTIONS = {
  /** strict 模式：warn 也视为 fail */
  strict: false,
  /** 最低置信度要求（低于此值触发 warning） */
  minConfidence: 70,
  /** 最低 rollout 阶段才算"已充分验证" */
  minRolloutStageForPass: 50,
};

// ─── 检查项定义 ──────────────────────────────────────

/**
 * 执行所有 RC 检查。
 *
 * @param {object} params
 * @param {object} params.readiness - 就绪评估结果
 *   { status: "pass"|"warn"|"fail", safeToReplace: boolean, score?: number }
 * @param {object} params.rolloutStage - 阶段晋级策略结果
 *   { action: "promote"|"freeze"|"rollback"|"activate_kill_switch", currentStage: number, confidence?: number }
 * @param {object} params.rollbackReport - 回滚报告
 *   { recommendation: "keep_enabled"|"disable_replacement"|"activate_kill_switch" }
 * @param {object} params.circuitBreaker - 断路器快照
 *   { state: "closed"|"open"|"half_open" }
 * @param {object} params.testSummary - 测试摘要
 *   { total?: number, failed?: number, regressions?: number, pass?: number }
 * @param {object} [params.options] - 可选项
 *   { strict?: boolean, minConfidence?: number, minRolloutStageForPass?: number }
 *
 * @returns {object}
 *   - status: "pass" | "warn" | "fail"
 *   - releaseCandidate: boolean (status === "pass" → true, strict 下 warn 也可能 false)
 *   - confidence: 0-100
 *   - blockers: string[]
 *   - warnings: string[]
 *   - checks: object — 每个检查项的详细结果
 *   - recommendation: string
 */
export function evaluateReleaseCandidate(params) {
  if (!params || typeof params !== "object") {
    return _buildRC(RC_FAIL, false, 0, ["没有提供有效参数"], [], {}, "无法评估 RC 条件。请提供完整的 readiness / rollout / rollback / circuit / test 数据。");
  }

  const {
    readiness = {},
    rolloutStage = {},
    rollbackReport = {},
    circuitBreaker = {},
    testSummary = {},
    options = {},
  } = params;

  const opts = { ...DEFAULT_OPTIONS, ...(options || {}) };

  const blockers = [];
  const warnings = [];
  const checks = {};

  // ── 提取值 ────────────────────────────────────
  const readinessStatus = readiness.status || "unknown";
  const safeToReplace = readiness.safeToReplace === true;
  const readinessScore = typeof readiness.score === "number" ? readiness.score : null;

  const rolloutAction = rolloutStage.action || "unknown";
  const currentStage = typeof rolloutStage.currentStage === "number" ? rolloutStage.currentStage : 0;
  const rolloutConfidence = typeof rolloutStage.confidence === "number" ? rolloutStage.confidence : 0;

  const rollbackRec = rollbackReport.recommendation || "unknown";

  const circuitState = circuitBreaker.state || "unknown";

  const testsTotal = typeof testSummary.total === "number" ? testSummary.total : 0;
  const testsFailed = typeof testSummary.failed === "number" ? testSummary.failed : 0;
  const testsRegressions = typeof testSummary.regressions === "number" ? testSummary.regressions : 0;
  const testsPass = typeof testSummary.pass === "number" ? testSummary.pass : (testsTotal - testsFailed);

  // ═══════════════════════════════════════════════════
  // 检查 1：Readiness
  // ═══════════════════════════════════════════════════
  checks.readiness = {
    status: readinessStatus,
    safeToReplace,
    score: readinessScore,
    pass: readinessStatus === "pass" && safeToReplace,
  };

  if (readinessStatus === "fail") {
    blockers.push("就绪评估 FAIL — replacement 质量不达标");
  } else if (!checks.readiness.pass) {
    if (readinessStatus === "warn") {
      warnings.push("就绪评估 WARN — 质量存疑");
    } else if (readinessStatus === "unknown") {
      blockers.push("就绪评估状态未知 — 无法判断是否安全");
    } else {
      blockers.push("就绪评估未通过 — safeToReplace 为 false");
    }
  }

  // ═══════════════════════════════════════════════════
  // 检查 2：Rollout Stage
  // ═══════════════════════════════════════════════════
  // 允许 promote 的任意阶段 或 100% freeze
  const isRolloutOk =
    rolloutAction === "promote" ||
    (rolloutAction === "freeze" && currentStage >= 100);

  checks.rolloutStage = {
    action: rolloutAction,
    currentStage,
    confidence: rolloutConfidence,
    pass: isRolloutOk,
  };

  if (rolloutAction === "rollback") {
    blockers.push(`阶段晋级建议 ROLLBACK — 灰度应回退`);
  } else if (rolloutAction === "activate_kill_switch") {
    blockers.push(`阶段晋级建议 ACTIVATE_KILL_SWITCH — 灰度应立即关闭`);
  } else if (rolloutAction === "freeze" && currentStage < 100) {
    warnings.push(`灰度停留在 ${currentStage}%（未达到 100%），阶段晋级建议 freeze`);
  } else if (rolloutAction === "unknown") {
    blockers.push("阶段晋级状态未知");
  }

  // confidence 偏低
  if (checks.rolloutStage.pass && rolloutConfidence > 0 && rolloutConfidence < opts.minConfidence) {
    warnings.push(`阶段晋级置信度 ${rolloutConfidence} 偏低（< ${opts.minConfidence}）`);
  }

  // 未达充分验证阶段
  if (currentStage < opts.minRolloutStageForPass && currentStage < 100 && isRolloutOk) {
    warnings.push(`当前灰度阶段 ${currentStage}% 未达到充分验证水平（${opts.minRolloutStageForPass}%）`);
  }

  // ═══════════════════════════════════════════════════
  // 检查 3：Rollback Report
  // ═══════════════════════════════════════════════════
  checks.rollback = {
    recommendation: rollbackRec,
    pass: rollbackRec === "keep_enabled",
  };

  if (rollbackRec === "disable_replacement") {
    blockers.push("回滚报告建议 DISABLE_REPLACEMENT — replacement 不应启用");
  } else if (rollbackRec === "activate_kill_switch") {
    blockers.push("回滚报告建议 ACTIVATE_KILL_SWITCH — replacement 必须关闭");
  } else if (rollbackRec === "unknown") {
    blockers.push("回滚报告状态未知");
  }

  // ═══════════════════════════════════════════════════
  // 检查 4：Circuit Breaker
  // ═══════════════════════════════════════════════════
  checks.circuitBreaker = {
    state: circuitState,
    pass: circuitState === "closed",
  };

  if (circuitState === "open") {
    blockers.push("断路器 OPEN — replacement 已被自动阻断");
  } else if (circuitState === "half_open") {
    warnings.push("断路器 HALF_OPEN — 正在探测恢复中");
  } else if (circuitState === "unknown") {
    blockers.push("断路器状态未知");
  }

  // ═══════════════════════════════════════════════════
  // 检查 5：测试
  // ═══════════════════════════════════════════════════
  checks.tests = {
    total: testsTotal,
    failed: testsFailed,
    regressions: testsRegressions,
    pass: testsFailed === 0 && testsRegressions === 0,
  };

  if (testsFailed > 0) {
    blockers.push(`${testsFailed} 个测试失败 — 必须全部通过`);
  }
  if (testsRegressions > 0) {
    blockers.push(`${testsRegressions} 个回归测试失败 — 必须全部通过`);
  }
  if (testsTotal === 0) {
    warnings.push("未提供测试摘要数据 — 假设测试通过");
    // 没有测试数据时不阻塞
    checks.tests.pass = true;
  }

  // ═══════════════════════════════════════════════════
  // 决策
  // ═══════════════════════════════════════════════════
  const allMandatoryPass = Object.values(checks).every(c => c.pass !== false);

  let status;
  let releaseCandidate;

  if (blockers.length > 0) {
    status = RC_FAIL;
    releaseCandidate = false;
  } else if (warnings.length > 0) {
    if (opts.strict) {
      status = RC_FAIL;
      releaseCandidate = false;
      blockers.push("strict 模式开启：存在警示项，视为阻塞");
    } else {
      status = RC_WARN;
      releaseCandidate = true;
    }
  } else {
    status = RC_PASS;
    releaseCandidate = true;
  }

  // 置信度计算
  const passedChecks = Object.values(checks).filter(c => c.pass === true).length;
  const totalChecks = Object.values(checks).filter(c => c.pass !== undefined).length;
  const baseConfidence = totalChecks > 0 ? Math.round((passedChecks / totalChecks) * 100) : 50;
  const blockerPenalty = blockers.length * 15;
  const warningPenalty = warnings.length * 5;
  const confidence = Math.max(0, baseConfidence - blockerPenalty - warningPenalty);

  // 建议文本
  let recommendation;
  if (status === RC_PASS) {
    recommendation = "所有检查项通过。系统已满足 Release Candidate 条件，可以进入最终发布候选。";
  } else if (status === RC_WARN) {
    const warnItems = warnings.map(w => `  - ${w}`).join("\n");
    recommendation = `存在 ${warnings.length} 项警示，但无阻塞项。可以进入 RC，建议关注：\n${warnItems}`;
  } else {
    const blockItems = blockers.map(b => `  - ${b}`).join("\n");
    recommendation = `存在 ${blockers.length} 项阻塞 + ${warnings.length} 项警示。不能进入 RC。阻塞项：\n${blockItems}`;
  }

  return _buildRC(status, releaseCandidate, confidence, blockers, warnings, checks, recommendation);
}

// ─── 内部工具 ────────────────────────────────────────

function _buildRC(status, releaseCandidate, confidence, blockers, warnings, checks, recommendation) {
  return {
    status,
    releaseCandidate,
    confidence: Math.min(100, Math.max(0, Math.round(confidence))),
    blockers,
    warnings,
    checks,
    recommendation,
  };
}
