/**
 * Failure Classifier — categorizes tool failures for smart retry.
 */

export type FailureType =
  | 'compile_error'
  | 'type_error'
  | 'test_failure'
  | 'permission_denied'
  | 'timeout'
  | 'file_not_found'
  | 'syntax_error'
  | 'unknown'

export interface ClassifiedFailure {
  type: FailureType
  guidance: string
  retryable: boolean
}

// Patterns for failure classification
const PATTERNS: Array<{
  type: FailureType
  patterns: RegExp[]
  guidance: string
  retryable: boolean
}> = [
  {
    type: 'compile_error',
    patterns: [
      /error TS\d+/i,
      /compilation failed/i,
      /cannot find module/i,
      /unexpected token/i,
      /SyntaxError/,
      /Build failed/i,
    ],
    guidance:
      'Read the error output carefully. Identify the specific file and line number. Apply a targeted fix to that exact location.',
    retryable: true,
  },
  {
    type: 'type_error',
    patterns: [
      /Type '.*' is not assignable/i,
      /Property '.*' does not exist/i,
      /Argument of type '.*' is not assignable/i,
      /cannot find name/i,
    ],
    guidance:
      'This is a type error. Check the expected type at the error location and fix the type mismatch. Do not cast to `any`.',
    retryable: true,
  },
  {
    type: 'test_failure',
    patterns: [
      /FAIL/,
      /AssertionError/i,
      /Expected.*Received/i,
      /expect\(.*\)\./,
      /test failed/i,
      /✕|✗|FAILED/,
    ],
    guidance:
      'Read the test assertion: what was expected vs what was received. Understand the discrepancy before making changes. Fix the implementation, not the test (unless the test itself is wrong).',
    retryable: true,
  },
  {
    type: 'permission_denied',
    patterns: [
      /permission denied/i,
      /EACCES/i,
      /not permitted/i,
      /access denied/i,
    ],
    guidance:
      'This operation was denied due to permissions. Queue for user approval or try an alternative approach that does not require elevated permissions.',
    retryable: false,
  },
  {
    type: 'timeout',
    patterns: [
      /timed? ?out/i,
      /ETIMEDOUT/i,
      /deadline exceeded/i,
      /operation took too long/i,
    ],
    guidance:
      'The operation timed out. Retry with a smaller scope or split into subtasks. If this is a network operation, check connectivity.',
    retryable: true,
  },
  {
    type: 'file_not_found',
    patterns: [
      /ENOENT/i,
      /no such file/i,
      /file not found/i,
      /does not exist/i,
    ],
    guidance:
      'The target file does not exist. Verify the file path is correct. Use Glob to search for the actual location.',
    retryable: true,
  },
  {
    type: 'syntax_error',
    patterns: [
      /SyntaxError/i,
      /Unexpected token/i,
      /Unterminated string/i,
      /Invalid regular expression/i,
    ],
    guidance:
      'There is a syntax error. Read the error message for the exact location and fix the syntax issue.',
    retryable: true,
  },
]

/**
 * Classify a tool failure based on the error output.
 */
export function classifyFailure(errorOutput: string): ClassifiedFailure {
  for (const { type, patterns, guidance, retryable } of PATTERNS) {
    for (const pattern of patterns) {
      if (pattern.test(errorOutput)) {
        return { type, guidance, retryable }
      }
    }
  }

  return {
    type: 'unknown',
    guidance:
      'The error type is unclear. Read the full error output, understand what went wrong, and try a different approach. If this persists after 2 attempts, ask the user for guidance.',
    retryable: true,
  }
}
