/**
 * Doom Loop 检测器
 *
 * 检测模型是否陷入重复工具调用的死循环。
 * 参考 OpenCode 和 OpenHands 的实现。
 */

import { createHash } from 'crypto';

/**
 * 工具调用记录
 */
export interface ToolCallRecord {
  toolName: string;
  inputHash: string;
}

/**
 * Doom Loop 检测器接口
 */
export interface DoomLoopDetector {
  /** 记录工具调用 */
  record(toolName: string, input: unknown): void;
  /** 检测是否触发 doom loop */
  isTriggered(): boolean;
  /** 重置记录（新对话时调用） */
  reset(): void;
  /** 获取当前状态描述（用于日志） */
  getStatus(): string;
  /** 获取最后重复的工具名称（触发时使用） */
  getLastToolName(): string | null;
}

/**
 * Doom Loop 检测阈值
 * 连续 N 次相同的工具调用（相同工具名 + 相同参数）触发检测
 */
export const DOOM_LOOP_THRESHOLD = 3;

/**
 * 计算输入参数的哈希值
 */
function hashInput(input: unknown): string {
  const str = JSON.stringify(input, Object.keys(input as object).sort());
  return createHash('md5').update(str).digest('hex').slice(0, 16);
}

/**
 * 创建 Doom Loop 检测器
 */
export function createDoomLoopDetector(threshold = DOOM_LOOP_THRESHOLD): DoomLoopDetector {
  const history: ToolCallRecord[] = [];
  let triggered = false;
  let lastToolName: string | null = null;

  return {
    record(toolName: string, input: unknown): void {
      const inputHash = hashInput(input);
      history.push({ toolName, inputHash });

      // 只保留最近 threshold 条记录
      if (history.length > threshold) {
        history.shift();
      }

      // 检测是否触发
      if (history.length >= threshold) {
        const lastN = history.slice(-threshold);
        const first = lastN[0];
        const allSame = lastN.every(
          (call) => call.toolName === first.toolName && call.inputHash === first.inputHash
        );

        if (allSame) {
          triggered = true;
          lastToolName = first.toolName;
        }
      }
    },

    isTriggered(): boolean {
      return triggered;
    },

    reset(): void {
      history.length = 0;
      triggered = false;
      lastToolName = null;
    },

    getStatus(): string {
      if (triggered) {
        return `Doom loop detected: ${lastToolName} called ${threshold} times with same input`;
      }
      return `Normal: ${history.length} calls recorded`;
    },

    getLastToolName(): string | null {
      return lastToolName;
    },
  };
}

/**
 * MAX_STEPS 达到时的警告提示
 * 注入到 system prompt 中，让模型输出总结
 */
export const MAX_STEPS_WARNING = `
CRITICAL - MAXIMUM STEPS REACHED

The maximum number of steps allowed for this task has been reached. Tools are disabled until next user input. Respond with text only.

STRICT REQUIREMENTS:
1. Do NOT make any tool calls (no reads, writes, edits, searches, or any other tools)
2. MUST provide a text response summarizing work done so far
3. This constraint overrides ALL other instructions

Please summarize:
1. What has been completed
2. What remains to be done
3. Any recommendations for next steps
`;

/**
 * Doom Loop 触发时的警告提示
 */
export const DOOM_LOOP_WARNING = `
WARNING - DOOM LOOP DETECTED

The same tool call has been repeated multiple times with identical inputs, indicating a potential infinite loop. Tools are temporarily disabled.

Please:
1. Explain what you were trying to accomplish
2. Describe why the repeated calls might not be working
3. Suggest an alternative approach
`;
