// Enhanced error types
export interface TypedError extends Error {
  type: 'network' | 'http' | 'timeout' | 'circuit' | 'offline'
  status?: number
  retryable: boolean
  retryAfter?: number
  suggestions: string[]
  debug: () => void
  // Additional context
  url?: string
  method?: string
  duration?: number
  attempt?: number
  timestamp?: number
}

// Error context for better debugging
export interface ErrorContext {
  method?: string
  attempt?: number
  duration?: number
  headers?: Record<string, string>
  body?: any
}

// Error creation utilities
export function createHttpError(response: Response, url: string, context?: ErrorContext): TypedError {
  const method = context?.method || 'GET'
  const attempt = context?.attempt
  const duration = context?.duration
  
  // Enhanced error message with context
  let message = `HTTP ${response.status}: ${response.statusText} at ${method} ${url}`
  if (attempt && attempt > 1) {
    message += ` (attempt ${attempt})`
  }
  if (duration) {
    message += ` after ${duration.toFixed(0)}ms`
  }
  
  const error = new Error(message) as TypedError
  error.type = 'http'
  error.status = response.status
  error.retryable = response.status >= 500 || response.status === 408 || response.status === 429
  error.suggestions = getErrorSuggestions(response.status)
  error.url = url
  error.method = method
  if (duration !== undefined) error.duration = duration
  if (attempt !== undefined) error.attempt = attempt
  error.timestamp = Date.now()
  
  if (response.status === 429) {
    const retryAfter = response.headers.get('retry-after')
    error.retryAfter = retryAfter ? parseInt(retryAfter) * 1000 : 60000
  }
  
  error.debug = () => {
    console.group(`🚨 HTTP Error Debug`)
    console.log('URL:', url)
    console.log('Method:', method)
    console.log('Status:', response.status, response.statusText)
    console.log('Timestamp:', new Date(error.timestamp!).toISOString())
    if (attempt) console.log('Attempt:', attempt)
    if (duration) console.log('Duration:', `${duration}ms`)
    console.log('Headers:', Object.fromEntries(response.headers.entries()))
    if (context?.body) console.log('Request Body:', context.body)
    console.log('Suggestions:', error.suggestions)
    console.groupEnd()
  }
  
  return error
}

export function enhanceError(error: any, url: string, context?: ErrorContext): TypedError {
  if (error.type) return error // Already enhanced
  
  const enhanced = error as TypedError
  enhanced.type = 'network'
  enhanced.retryable = true
  enhanced.url = url
  enhanced.method = context?.method || 'GET'
  if (context?.duration !== undefined) enhanced.duration = context.duration
  if (context?.attempt !== undefined) enhanced.attempt = context.attempt
  enhanced.timestamp = Date.now()
  
  // Enhanced error message
  if (context) {
    const originalMessage = error.message || 'Network error'
    let enhancedMessage = `${originalMessage} at ${enhanced.method} ${url}`
    if (context.attempt && context.attempt > 1) {
      enhancedMessage += ` (attempt ${context.attempt})`
    }
    if (context.duration) {
      enhancedMessage += ` after ${context.duration.toFixed(0)}ms`
    }
    enhanced.message = enhancedMessage
  }
  
  enhanced.suggestions = [
    'Check network connection',
    'Verify URL is correct',
    'Try again in a moment',
    error.code === 'ENOTFOUND' ? 'DNS lookup failed - check the domain' : null,
    error.code === 'ETIMEDOUT' ? 'Request timed out - server may be slow' : null
  ].filter(Boolean) as string[]
  
  enhanced.debug = () => {
    console.group(`🚨 Network Error Debug`)
    console.log('URL:', url)
    console.log('Method:', enhanced.method)
    console.log('Error:', error.message)
    console.log('Error Code:', error.code)
    console.log('Timestamp:', new Date(enhanced.timestamp!).toISOString())
    if (enhanced.attempt) console.log('Attempt:', enhanced.attempt)
    if (enhanced.duration) console.log('Duration:', `${enhanced.duration}ms`)
    console.log('Stack:', error.stack)
    console.groupEnd()
  }
  
  return enhanced
}

function getErrorSuggestions(status: number): string[] {
  switch (status) {
    case 400:
      return ['Check request body format', 'Validate required fields', 'Review API documentation']
    case 401:
      return ['Add authentication header', 'Check if token is expired', 'Verify API key']
    case 403:
      return ['Check user permissions', 'Verify API key scope', 'Contact API administrator']
    case 404:
      return ['Verify endpoint URL', 'Check API version', 'Confirm resource exists']
    case 429:
      return ['Implement rate limiting', 'Add retry logic', 'Consider request batching']
    case 500:
      return ['Try again later', 'Check API status page', 'Report to API provider']
    case 502:
    case 503:
    case 504:
      return ['Service temporarily unavailable', 'Try again in a few minutes', 'Check API status']
    default:
      return ['Check network connection', 'Review request details', 'Consult API documentation']
  }
}