/**
 * Self-Healing Retry Strategy — classifies failures and appends structured
 * guidance instead of passing raw errors back to the model.
 *
 * Integrates with the wander detector: same failure type 3+ times triggers
 * wander escalation.
 */

import { logForDebugging } from '../../utils/debug.js'
import {
  registerPostSamplingHook,
  type REPLHookContext,
} from '../../utils/hooks/postSamplingHooks.js'
import { classifyFailure, type ClassifiedFailure } from './classifier.js'

const SYSTEM_CONTEXT_KEY = 'retryGuidance'

// Track consecutive failures of the same type
let consecutiveSameType = 0
let lastFailureType: string | null = null

/**
 * PostSamplingHook that detects tool failures in the recent turn
 * and injects structured retry guidance into the system context.
 */
async function retryStrategyHook(context: REPLHookContext): Promise<void> {
  const { messages, systemContext } = context

  // Find the most recent user message with tool results
  const recentUser = messages
    .filter((m) => m.type === 'user')
    .at(-1)

  if (!recentUser) {
    delete systemContext[SYSTEM_CONTEXT_KEY]
    return
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const content = (recentUser as any).message?.content
  if (!Array.isArray(content)) {
    delete systemContext[SYSTEM_CONTEXT_KEY]
    return
  }

  // Look for error results
  const errorResults = content.filter(
    (b: { type: string; is_error?: boolean }) =>
      b.type === 'tool_result' && b.is_error,
  )

  if (errorResults.length === 0) {
    // No errors — clear guidance and reset tracking
    delete systemContext[SYSTEM_CONTEXT_KEY]
    consecutiveSameType = 0
    lastFailureType = null
    return
  }

  // Classify the first error
  const errorText = extractErrorText(errorResults[0])
  const classification = classifyFailure(errorText)

  // Track consecutive same-type failures
  if (classification.type === lastFailureType) {
    consecutiveSameType++
  } else {
    consecutiveSameType = 1
    lastFailureType = classification.type
  }

  logForDebugging(
    `Retry strategy: ${classification.type} (${consecutiveSameType} consecutive)`,
  )

  // Build guidance message
  const guidanceLines = [
    '<retry-guidance>',
    `Failure type: ${classification.type}`,
    `Guidance: ${classification.guidance}`,
  ]

  if (consecutiveSameType >= 3) {
    guidanceLines.push(
      `WARNING: Same failure type ${consecutiveSameType} times in a row.`,
      'You MUST try a fundamentally different approach or ask the user for help.',
    )
  } else if (consecutiveSameType >= 2) {
    guidanceLines.push(
      'This is the second occurrence. Consider a different strategy.',
    )
  }

  if (!classification.retryable) {
    guidanceLines.push(
      'This failure type is NOT retryable. Do not attempt the same operation again.',
    )
  }

  guidanceLines.push('</retry-guidance>')
  systemContext[SYSTEM_CONTEXT_KEY] = guidanceLines.join('\n')
}

/**
 * Extract error text from a tool result block.
 */
function extractErrorText(
  block: { content?: string | Array<{ text?: string }> },
): string {
  if (typeof block.content === 'string') return block.content
  if (Array.isArray(block.content)) {
    return block.content
      .map((c: { text?: string }) => c.text ?? '')
      .join('\n')
  }
  return ''
}

/**
 * Initialize the retry strategy system.
 */
export function initRetryStrategy(): void {
  registerPostSamplingHook(retryStrategyHook)
  logForDebugging('Retry strategy initialized')
}

// Re-export
export { classifyFailure } from './classifier.js'
export type { FailureType, ClassifiedFailure } from './classifier.js'
