'use strict';

/**
 * Detect the current coding phase from tool call history.
 * Used for per-turn model selection in the coding agent loop.
 */

const PHASES = {
  PLANNING: 'coding:planning',
  EXPLORATION: 'coding:exploration',
  GENERATION: 'coding:generation',
  DEBUGGING: 'coding:debugging',
  REFACTORING: 'coding:refactoring',
  TESTING: 'coding:testing',
  REVIEW: 'coding:review',
};

const EXPLORATION_TOOLS = new Set(['read_file', 'glob', 'grep_files', 'list_directory', 'lsp_symbols']);
const GENERATION_TOOLS = new Set(['write_file', 'edit_file', 'apply_patch', 'multi_edit']);
const TESTING_TOOLS = new Set(['run_shell']); // when running test commands
const PLANNING_TOOLS = new Set(['update_todos']);

/**
 * Detect the current coding phase based on recent tool call history.
 * @param {Array<{name: string, input?: object}>} recentToolCalls - Last N tool calls
 * @param {number} turnNumber - Current turn in the agent loop
 * @param {number} totalTurns - Max turns
 * @returns {string} Phase identifier (e.g., 'coding:planning')
 */
function detectPhase(recentToolCalls, turnNumber = 0, totalTurns = 50) {
  if (!recentToolCalls || recentToolCalls.length === 0) {
    // First turn is usually planning
    return turnNumber <= 1 ? PHASES.PLANNING : PHASES.EXPLORATION;
  }

  // Look at last 3 tool calls for pattern detection
  const recent = recentToolCalls.slice(-3);
  const recentNames = recent.map(t => typeof t === 'string' ? t : t.name || '');

  // Check for planning signals
  if (recentNames.some(n => PLANNING_TOOLS.has(n))) {
    return PHASES.PLANNING;
  }

  // Check for testing signals (run_shell with test-related commands, or string hints)
  const testingCalls = recent.filter(t => {
    if (typeof t === 'string') return /test|jest|pytest|mocha|vitest|spec/i.test(t);
    const name = t.name;
    if (name !== 'run_shell') return false;
    const cmd = (t.input || {}).command || '';
    return /test|jest|pytest|mocha|vitest|spec|lint|typecheck|tsc/i.test(cmd);
  });
  if (testingCalls.length > 0) {
    return PHASES.TESTING;
  }

  // Check for review signals (late-stage reading + diagnostics)
  if (turnNumber > totalTurns * 0.75) {
    const allExploration = recentNames.every(n => EXPLORATION_TOOLS.has(n));
    if (allExploration) return PHASES.REVIEW;
  }

  // Count tool type dominance
  const explorationCount = recentNames.filter(n => EXPLORATION_TOOLS.has(n)).length;
  const generationCount = recentNames.filter(n => GENERATION_TOOLS.has(n)).length;

  // Check for debugging signals (interleaving reads and edits after errors)
  const hasError = recent.some(t => {
    const result = typeof t === 'object' ? t.result || '' : '';
    return /error|Error|FAIL|failed|exception/i.test(String(result));
  });
  if (hasError && generationCount > 0) {
    return PHASES.DEBUGGING;
  }

  // Dominant pattern
  if (generationCount > explorationCount) {
    return PHASES.GENERATION;
  }
  if (explorationCount > 0 && generationCount === 0) {
    return PHASES.EXPLORATION;
  }

  // Early turns = planning/exploration, later = generation
  if (turnNumber <= 2) return PHASES.PLANNING;
  return PHASES.GENERATION;
}

/**
 * Get the recommended model for a coding phase.
 * Queries brain for the best model for the detected phase.
 * Falls back to the general 'coding' model if no phase-specific data.
 * @param {string} phase - Phase from detectPhase()
 * @param {object} brain - Brain instance
 * @returns {{ modelId: string, reason: string } | null}
 */
function getModelForPhase(phase, brain) {
  if (!brain) return null;

  // Try phase-specific model first
  const phaseDefault = brain.getModelDefault(phase);
  if (phaseDefault?.model_registry_id) {
    return {
      modelId: phaseDefault.model_registry_id,
      reason: `Best model for ${phase} based on ${phaseDefault.strategy || 'eval'} data`,
    };
  }

  // Fall back to general coding model
  const codingDefault = brain.getModelDefault('coding');
  if (codingDefault?.model_registry_id) {
    return {
      modelId: codingDefault.model_registry_id,
      reason: `Fallback to general coding model (no ${phase}-specific data)`,
    };
  }

  return null;
}

module.exports = {
  PHASES,
  detectPhase,
  getModelForPhase,
  EXPLORATION_TOOLS,
  GENERATION_TOOLS,
  TESTING_TOOLS,
  PLANNING_TOOLS,
};
