/**
 * HeartFlow Counterfactual Engine v2.1.0
 *
 * "反者道之动" — 反向思考的力量
 *
 * 道论启示：真正的智慧来自对自身的质疑。
 * 当心虫给出答案时，它需要同时生成"反方"——
 * 不是为了辩论，而是为了让答案更接近真实。
 *
 * 核心思想来源：
 * - 反者道之动（《道德经》第40章）
 * - CRITIC (Gou et al., 2024) - 外部验证批判
 * - Self-Refine Without External Feedback (arXiv 2602.11234) - 内在自我改进
 * - Double-loop learning (Argyris) - 双环学习
 * - 对话起源召回法（heartflow-persuasion-method v1.2.0）
 * - Regret Minimization with Adaptive Opponents (arXiv 2026) —— 新增后悔最小化框架
 *
 * 功能：
 * 1. 反方生成：给定答案，生成挑战性反方观点
 * 2. 前提攻击：质疑答案所依赖的隐含前提
 * 3. 归因还原：将答案还原到对话起源，验证是否走偏
 * 4. 修正输出：在原答案中加入"反方视角"，让用户看到多维
 * 5. 后悔最小化：评估答案面对反方观点和前提挑战时的稳健性，选择最低后悔方案
 */

class CounterfactualEngine {
  constructor(options = {}) {
    this.mode = options.mode || 'balanced';  // balanced | aggressive | gentle
    this.maxOpposingViews = options.maxOpposingViews || 2;
    this.maxPremiseChallenges = options.maxPremiseChallenges || 2;
    this.recordHistory = options.recordHistory !== false;

    // 反方生成的历史（用于学习）
    this.history = [];
    this.premiseSignals = [
      // 触发词：这些词暗示答案可能依赖了隐含前提
      '当然', '显然', '必然', '一定', '肯定',
      '应该', '必须', '毫无疑问', '毫无疑问',
      '这就说明', '这意味着', '这证明了',
      '很明显', '很明显地', '不言而喻',
    ];
    this.certaintySignals = [
      // 触发词：这些词暗示答案过于确定
      '绝对是', '一定是', '必然是', '毫无疑问',
      '没有争议', '无可置疑', '不容置疑',
      '唯一正确', '正确答案', '就是', '绝对正确',
    ];
  }

  /**
   * 核心API：给定答案，生成反方视角
   * @param {string} answer - 心虫给出的答案
   * @param {object} context - { userQuery, reasoning, evidence, alternatives (可选), regretWeights (可选) }
   * @returns {object} 反方分析结果
   */
  analyze(answer = '', context = {}) {
    if (!answer || answer.trim().length < 5) {
      return { relevant: false, reason: '答案过短，跳过反方生成' };
    }

    const result = {
      relevant: true,
      mode: this.mode,
      timestamp: new Date().toISOString(),

      // 反方观点
      opposingViews: this.generateOpposingViews(answer, context),

      // 前提挑战
      premiseChallenges: this.challengePremises(answer, context),

      // 归因还原
      originRecall: this.recallOrigin(context),

      // 置信度调整
      confidenceAdjustment: this.computeConfidenceShift(answer),

      // 修正建议
      refinement: this.suggestRefinement(answer, context),

      // 原始答案是否需要调整
      verdict: this.computeVerdict(answer),
    };

    // 后悔最小化分析（如果提供了备选答案）
    if (context && Array.isArray(context.alternatives) && context.alternatives.length > 0) {
      const regretResult = this.regretMinimizedSelection(
        [answer, ...context.alternatives],
        context,
        context.regretWeights || {}
      );
      result.regretAnalysis = regretResult;
    }

    if (this.recordHistory) {
      this.history.push({
        answer: answer.slice(0, 200),
        context: context.userQuery?.slice(0, 100),
        verdict: result.verdict,
        ts: result.timestamp,
      });
      if (this.history.length > 100) this.history.shift();
    }

    return result;
  }

  /**
   * 生成反方观点
   * 核心逻辑：不是寻找"正确答案"，而是找到"可能错的地方"
   */
  generateOpposingViews(answer, context = {}) {
    const views = [];

    // 1. 从语气检测反方
    const toneIssues = this.detectToneIssues(answer);
    if (toneIssues.length > 0 && this.mode !== 'gentle') {
      views.push({
        type: 'tone',
        challenge: '语气过于确定，可能忽略了其他可能性',
        detail: toneIssues,
        severity: 'medium',
      });
    }

    // 2. 从逻辑结构生成反方
    const logicIssues = this.detectLogicGaps(answer);
    if (logicIssues.length > 0) {
      views.push({
        type: 'logic',
        challenge: '逻辑链存在可质疑的环节',
        detail: logicIssues,
        severity: 'medium',
      });
    }

    // 3. 从归因还原生成反方
    if (context.userQuery) {
      const attributionGap = this.checkAttributionGap(answer, context.userQuery);
      if (attributionGap) {
        views.push({
          type: 'attribution',
          challenge: '答案可能偏离了原始问题',
          detail: attributionGap,
          severity: 'high',
        });
      }
    }

    // 4. 生成"如果相反"反方（最强力）
    const contraryScenario = this.generateContraryScenario(answer, context);
    if (contraryScenario) {
      views.push({
        type: 'contrary',
        challenge: '如果情况相反，结果会不同吗？',
        detail: contraryScenario,
        severity: 'low',
      });
    }

    return views.slice(0, this.maxOpposingViews);
  }

  /**
   * 挑战答案的隐含前提
   * 核心：很多答案的谬误不在结论，而在前提
   */
  challengePremises(answer, context = {}) {
    const challenges = [];

    // 1. 检测"前提信号词"
    for (const signal of this.premiseSignals) {
      if (answer.includes(signal)) {
        challenges.push({
          signal,
          question: this.generatePremiseQuestion(signal, answer),
          type: 'premise_signal',
          severity: 'medium',
        });
      }
    }

    // 2. 检测"确定性信号词"
    for (const signal of this.certaintySignals) {
      if (answer.includes(signal)) {
        challenges.push({
          signal,
          question: '这个"必然"成立的条件是什么？有没有反例？',
          type: 'certainty_challenge',
          severity: 'high',
        });
      }
    }

    // 3. 检测因果关系
    const causalPhrases = answer.match(/因为(.*?)所以(.*?)[。.]/g) || [];
    for (const phrase of causalPhrases) {
      challenges.push({
        phrase,
        question: '这个因果关系是充分条件还是必要条件？',
        type: 'causal_challenge',
        severity: 'medium',
      });
    }

    return challenges.slice(0, this.maxPremiseChallenges);
  }

  /**
   * 归因还原：检查答案是否回到了对话起源
   * 来源：heartflow-persuasion-method v1.2.0 的"召回对话起源"
   */
  recallOrigin(context = {}) {
    const { userQuery, reasoning } = context;

    if (!userQuery) {
      return { relevant: false, reason: '无原始问题，无法归因还原' };
    }

    // 检查答案是否回应当了原始问题
    const answerKeywords = (reasoning || '').split(/\s+/).filter(w => w.length > 2);
    const queryKeywords = userQuery.split(/\s+/).filter(w => w.length > 2);

    const coverage = answerKeywords.filter(k =>
      queryKeywords.some(q => k.includes(q) || q.includes(k))
    ).length;

    const coverageRate = queryKeywords.length > 0
      ? coverage / queryKeywords.length
      : 1;

    return {
      relevant: true,
      query: userQuery.slice(0, 100),
      coverageRate: Math.round(coverageRate * 100) + '%',
      driftDetected: coverageRate < 0.5,
      note: coverageRate < 0.5
        ? '答案可能已偏离原始问题，建议回归'
        : '答案较好地回应当了原始问题',
    };
  }

  /**
   * 计算置信度调整
   */
  computeConfidenceShift(answer) {
    const certainSignals = this.certaintySignals.filter(s => answer.includes(s));
    const premiseSignals = this.premiseSignals.filter(s => answer.includes(s));
    const logicGaps = this.detectLogicGaps(answer).length;

    const shift = -(certainSignals.length * 0.15) - (logicGaps * 0.1) + (premiseSignals.length * 0.05);

    return {
      originalConfidence: 'high',
      confidence: certainSignals.length > 0 ? 'high' : 'medium',
      adjustedConfidence: shift < -0.4 ? 'low' : shift < -0.2 ? 'medium' : 'high',
      shift: Math.round(shift * 100) / 100,
      reasons: certainSignals.length > 0
        ? '检测到确定性信号，置信度下调'
        : '无明显确定性偏差',
    };
  }

  /**
   * 建议修正
   */
  suggestRefinement(answer, context = {}) {
    const views = this.generateOpposingViews(answer, context);
    const challenges = this.challengePremises(answer, context);

    if (views.length === 0 && challenges.length === 0) {
      return { needed: false, suggestion: null };
    }

    const suggestions = [];

    // 语气修正
    const toneViews = views.filter(v => v.type === 'tone');
    if (toneViews.length > 0) {
      suggestions.push('将语气从"确定"调整为"可能"或"也许"');
    }

    // 前提修正
    const premiseChallenge = challenges.find(c => c.type === 'premise_signal');
    if (premiseChallenge) {
      suggestions.push('在"前提假设"之前加上"在...情况下"');
    }

    // 确定性修正
    const certaintyChallenge = challenges.find(c => c.type === 'certainty_challenge');
    if (certaintyChallenge) {
      suggestions.push('将"必然"替换为"很可能"或"在大多数情况下"');
    }

    // 归因修正
    const originRecall = this.recallOrigin(context);
    if (originRecall.driftDetected) {
      suggestions.push('建议回到原始问题：' + originRecall.query);
    }

    return {
      needed: suggestions.length > 0,
      suggestion: suggestions.join('；') || null,
      count: suggestions.length,
    };
  }

  /**
   * 计算最终判定
   */
  computeVerdict(answer) {
    const issues = [
      ...this.certaintySignals.filter(s => answer.includes(s)),
      ...this.premiseSignals.filter(s => answer.includes(s)),
    ];
    const logicGaps = this.detectLogicGaps(answer);

    if (issues.length >= 3 || logicGaps.length >= 2) {
      return 'needs_revision';
    } else if (issues.length >= 1 || logicGaps.length >= 1) {
      return 'needs_adjustment';
    } else {
      return 'likely_correct';
    }
  }

  // ==================== 新增：后悔最小化（基于 Regret Minimization with Adaptive Opponents） ====================

  /**
   * 检查答案是否回应了某个反方观点（简单启发式）
   * @private
   */
  _answerAddressesView(answer, view) {
    const viewText = (view.challenge || '') + ' ' + (typeof view.detail === 'string' ? view.detail : '');
    const words = viewText.split(/\s+/).filter(w => w.length > 2);
    let matchCount = 0;
    for (const word of words) {
      if (answer.includes(word)) {
        matchCount++;
      }
    }
    // 如果答案中包含至少两个非停用词或 30% 的关键词，认为有回应
    return matchCount >= Math.max(2, Math.ceil(words.length * 0.3));
  }

  /**
   * 检查答案是否明确承认了前提挑战
   * @private
   */
  _answerAcknowledgesPremise(answer, challenge) {
    // 检测答案中是否包含条件化表述
    return /在.*情况下|取决于|视.*而定|可能不是|并非绝对|不一定|有条件/.test(answer);
  }

  /**
   * 评估给定答案的后悔分数（0~1，分数越高越稳健，后悔 = 1 - 分数）
   * 
   * 核心思想：将每个反方观点 / 前提挑战视为"自适应对手"，答案面对对手时的
   * 应对能力决定了其外部后悔。若答案能有效回应或条件化，则后悔低。
   * 
   * @param {string} answer - 要评估的答案
   * @param {object} context - 上下文（userQuery 等）
   * @param {object} weights - 各维度权重（可选）
   * @returns {object} 包含总分、后悔值、各分量得分
   */
  assessRegret(answer, context = {}, weights = {}) {
    const opposingViews = this.generateOpposingViews(answer, context);
    const premiseChallenges = this.challengePremises(answer, context);
    const originRecall = this.recallOrigin(context);
    const logicGaps = this.detectLogicGaps(answer);
    
    // 1. 反方抵抗力：答案对每个反方观点的回应程度
    let oppositionScore = 0;
    if (opposingViews.length > 0) {
      let addressed = 0;
      for (const view of opposingViews) {
        if (this._answerAddressesView(answer, view)) {
          addressed++;
        }
      }
      oppositionScore = addressed / opposingViews.length;
    } else {
      oppositionScore = 1; // 没有反方观点，此项完美
    }
    
    // 2. 前提明确性：答案是否包含了针对前提挑战的条件化表述
    let premiseScore = 0;
    if (premiseChallenges.length > 0) {
      let acknowledged = 0;
      for (const challenge of premiseChallenges) {
        if (this._answerAcknowledgesPremise(answer, challenge)) {
          acknowledged++;
        }
      }
      premiseScore = acknowledged / premiseChallenges.length;
    } else {
      premiseScore = 1;
    }
    
    // 3. 逻辑完整性：基于检测到的逻辑漏洞数量
    const gapCount = logicGaps.length;
    const logicScore = Math.max(0, 1 - gapCount * 0.25);
    
    // 4. 归因覆盖率：答案是否覆盖了原始问题关键词
    let attributionScore = 0.5;
    if (originRecall && typeof originRecall.coverageRate === 'string') {
      const rate = parseFloat(originRecall.coverageRate) / 100;
      if (!isNaN(rate)) {
        attributionScore = rate;
      }
    }
    
    // 权重组合（默认权重可被覆盖）
    const defaultWeights = { opposition: 0.3, premise: 0.3, logic: 0.2, attribution: 0.2 };
    const w = Object.assign({}, defaultWeights, weights);
    
    const totalScore = (oppositionScore * w.opposition) +
                       (premiseScore * w.premise) +
                       (logicScore * w.logic) +
                       (attributionScore * w.attribution);
    
    const regret = 1 - totalScore; // 0 表示无后悔，1 表示完全后悔
    
    return {
      totalScore: Math.round(totalScore * 100) / 100,
      regret: Math.round(regret * 100) / 100,
      components: {
        opposition: Math.round(oppositionScore * 100) / 100,
        premise: Math.round(premiseScore * 100) / 100,
        logic: Math.round(logicScore * 100) / 100,
        attribution: Math.round(attributionScore * 100) / 100,
      },
      details: {
        opposingViews,
        premiseChallenges,
        logicGaps,
        originRecall,
      },
    };
  }

  /**
   * 从多个候选答案中选择后悔最小的答案（外部后悔最小化）。
   * 
   * 算法：对每个候选答案计算后悔分数（1 - totalScore），选择 regret 最小的。
   * 同时计算"外部后悔"：如果选择了当前最佳而非其他候选，可能损失的分数。
   * 
   * @param {string[]} candidates - 候选答案数组
   * @param {object} context - 上下文
   * @param {object} weights - 各维度权重
   * @returns {object} 选择结果，包含 best、externalRegret 和所有候选项的评分
   */
  regretMinimizedSelection(candidates, context = {}, weights = {}) {
    if (!candidates || candidates.length === 0) {
      return { best: null, allScores: [], selectionMethod: 'none' };
    }
    
    const allScores = candidates.map((answer, index) => {
      const result = this.assessRegret(answer, context, weights);
      return { index, answer, ...result };
    });
    
    // 按 regret 升序排序（regret 越小越好）
    allScores.sort((a, b) => a.regret - b.regret);
    
    const best = allScores[0];
    // 外部后悔 = 最佳候选项得分与最差候选项得分之差（表示如果选错可能造成的最大损失）
    const worstScore = allScores[allScores.length - 1].totalScore;
    const externalRegret = Math.max(0, worstScore - best.totalScore);
    
    return {
      best: { answer: best.answer, score: best.totalScore, regret: best.regret },
      externalRegret: Math.round(externalRegret * 100) / 100,
      allScores: allScores.map(s => ({ index: s.index, score: s.totalScore, regret: s.regret })),
      selectionMethod: 'regret_minimization_with_adaptive_opponents',
      philosophy: '反者道之动，通过最小化面对反方观点时的后悔来选择最稳健的答案',
    };
  }

  // ===== 辅助方法（原有 + 重构） =====

  detectToneIssues(answer) {
    const matches = this.certaintySignals.filter(s => answer.includes(s));
    if (/绝对|必然|一定|显然|毫无疑问|无可置疑/.test(answer)) {
      matches.push('high_certainty_tone');
    }
    return [...new Set(matches)];
  }

  detectLogicGaps(answer) {
    const gaps = [];

    // 检测没有证据支撑的因果
    if (/因为(.*)所以(.*)/.test(answer) && !answer.includes('证据') && !answer.includes('数据')) {
      gaps.push('因果陈述缺少证据支撑');
    }

    // 检测过于概括的结论
    if (/所有|全部|每个|一切/.test(answer)) {
      gaps.push('使用全称量词，可能存在反例');
    }

    // 检测无来源的引用
    if (/研究表明?|研究显示|专家说|权威/.test(answer) && !answer.includes('arXiv') && !answer.includes('论文')) {
      gaps.push('引用缺乏具体来源');
    }

    return gaps;
  }

  checkAttributionGap(answer, query) {
    if (!query) return null;
    const queryWords = query.split(/\s+/).filter(w => w.length > 1);
    const answerWords = answer.split(/\s+/).filter(w => w.length > 1);
    const overlap = queryWords.filter(qw => answerWords.some(aw => aw.includes(qw) || qw.includes(aw)));
    if (overlap.length < queryWords.length * 0.3) {
      return {
        queryCoverage: Math.round(overlap.length / queryWords.length * 100) + '%',
        note: '答案与问题的关键词重叠度较低，可能存在漂移',
      };
    }
    return null;
  }

  generateContraryScenario(answer, context = {}) {
    // 简单的"如果相反"生成
    const negations = {
      '是': '不是',
      '有': '没有',
      '能': '不能',
      '会': '不会',
      '应该': '不应该',
      '好': '不好',
      '对': '不对',
    };

    for (const [word, neg] of Object.entries(negations)) {
      if (answer.includes(word) && answer.length < 500) {
        return `如果情况相反（将"${word}"替换为"${neg}"），这个答案还成立吗？`;
      }
    }
    return null;
  }

  generatePremiseQuestion(signal, answer) {
    const questions = {
      '当然': '这个"当然"成立的条件是什么？',
      '显然': '这个"显然"对所有人都是明显的吗？',
      '必然': '这个"必然"有没有反例？',
      '一定': '这个"一定"的例外是什么？',
      '应该': '"应该"和"是"之间的差距是什么？',
      '必须': '这个"必须"的约束条件是什么？',
      '毫无疑问': '真的没有疑问吗？谁能提出最有力的质疑？',
      '这就说明': '说明的原因充分吗？有没有其他解释？',
      '这意味着': '这个含义是唯一的吗？',
    };
    return questions[signal] || '这个判断的前提是什么？';
  }

  // ===== 信息API =====

  stats() {
    return {
      historySize: this.history.length,
      mode: this.mode,
      version: '2.1.0',
      premiseSignals: this.premiseSignals.length,
      certaintySignals: this.certaintySignals.length,
    };
  }

  recentHistory(limit = 10) {
    return this.history.slice(-limit);
  }
}

module.exports = { CounterfactualEngine };