'use strict';

const FailureScenario = Object.freeze({
  TRUST_PROMPT_UNRESOLVED: 'trust_prompt_unresolved',
  PROMPT_MISDELIVERY: 'prompt_misdelivery',
  STALE_BRANCH: 'stale_branch',
  COMPILE_RED: 'compile_red',
  MCP_HANDSHAKE_FAILURE: 'mcp_handshake_failure',
  PARTIAL_PLUGIN_STARTUP: 'partial_plugin_startup',
  PROVIDER_FAILURE: 'provider_failure',
});

const RecoveryStep = Object.freeze({
  ACCEPT_TRUST_PROMPT: 'accept_trust_prompt',
  REDIRECT_PROMPT_TO_AGENT: 'redirect_prompt_to_agent',
  REBASE_BRANCH: 'rebase_branch',
  CLEAN_BUILD: 'clean_build',
  RETRY_MCP_HANDSHAKE: 'retry_mcp_handshake',
  RESTART_PLUGIN: 'restart_plugin',
  RESTART_WORKER: 'restart_worker',
  ESCALATE_TO_HUMAN: 'escalate_to_human',
});

const RECIPES = Object.freeze({
  [FailureScenario.TRUST_PROMPT_UNRESOLVED]: [RecoveryStep.ACCEPT_TRUST_PROMPT, RecoveryStep.RESTART_WORKER],
  [FailureScenario.PROMPT_MISDELIVERY]: [RecoveryStep.REDIRECT_PROMPT_TO_AGENT, RecoveryStep.RESTART_WORKER],
  [FailureScenario.STALE_BRANCH]: [RecoveryStep.REBASE_BRANCH],
  [FailureScenario.COMPILE_RED]: [RecoveryStep.CLEAN_BUILD],
  [FailureScenario.MCP_HANDSHAKE_FAILURE]: [RecoveryStep.RETRY_MCP_HANDSHAKE],
  [FailureScenario.PARTIAL_PLUGIN_STARTUP]: [RecoveryStep.RESTART_PLUGIN],
  [FailureScenario.PROVIDER_FAILURE]: [RecoveryStep.RESTART_WORKER],
});

function recoveryRecipeFor(scenario) {
  const key = normalizeScenario(scenario);
  return {
    scenario: key,
    steps: [...(RECIPES[key] || [RecoveryStep.ESCALATE_TO_HUMAN])],
  };
}

function chooseRecovery({ scenario, attempts = {}, maxAttempts = 1 } = {}) {
  const key = normalizeScenario(scenario);
  const count = Number(attempts[key] || 0);
  if (count >= maxAttempts) {
    return {
      scenario: key,
      action: RecoveryStep.ESCALATE_TO_HUMAN,
      exhausted: true,
      attempts: count,
      reason: 'max_attempts_reached',
    };
  }
  const recipe = recoveryRecipeFor(key);
  return {
    scenario: key,
    action: recipe.steps[0] || RecoveryStep.ESCALATE_TO_HUMAN,
    steps: recipe.steps,
    exhausted: false,
    attempts: count,
    nextAttempts: { ...attempts, [key]: count + 1 },
  };
}

function scenarioFromFailure(input = {}) {
  const text = String(input.failureClass || input.failureKind || input.error || input.reason || '').toLowerCase();
  if (/trust/.test(text)) return FailureScenario.TRUST_PROMPT_UNRESOLVED;
  if (/prompt/.test(text)) return FailureScenario.PROMPT_MISDELIVERY;
  if (/branch|stale|diverge/.test(text)) return FailureScenario.STALE_BRANCH;
  if (/mcp|handshake/.test(text)) return FailureScenario.MCP_HANDSHAKE_FAILURE;
  if (/plugin/.test(text)) return FailureScenario.PARTIAL_PLUGIN_STARTUP;
  if (/compile|test|build/.test(text)) return FailureScenario.COMPILE_RED;
  return FailureScenario.PROVIDER_FAILURE;
}

function normalizeScenario(scenario) {
  const text = String(scenario || '').toLowerCase();
  return Object.values(FailureScenario).includes(text) ? text : FailureScenario.PROVIDER_FAILURE;
}

module.exports = {
  FailureScenario,
  RecoveryStep,
  chooseRecovery,
  recoveryRecipeFor,
  scenarioFromFailure,
};
