/**
 * Structured logging utility
 */

type LogLevel = 'debug' | 'info' | 'warn' | 'error'

interface LogEntry {
  level: LogLevel
  message: string
  timestamp: string
  context?: Record<string, unknown>
  error?: Error
}

class Logger {
  private logLevel: LogLevel

  constructor() {
    this.logLevel = (process.env.NODE_ENV === 'development' ? 'debug' : 'info') as LogLevel
  }

  private shouldLog(level: LogLevel): boolean {
    const levels: LogLevel[] = ['debug', 'info', 'warn', 'error']
    return levels.indexOf(level) >= levels.indexOf(this.logLevel)
  }

  private formatEntry(entry: LogEntry): string {
    const { level, message, timestamp, context, error } = entry
    const parts = [`[${timestamp}]`, `[${level.toUpperCase()}]`, message]

    if (context && Object.keys(context).length > 0) {
      parts.push(JSON.stringify(context))
    }

    if (error) {
      parts.push(`\nError: ${error.message}`)
      if (error.stack) {
        parts.push(`\nStack: ${error.stack}`)
      }
    }

    return parts.join(' ')
  }

  private log(level: LogLevel, message: string, context?: Record<string, unknown>, error?: Error) {
    if (!this.shouldLog(level)) {
      return
    }

    const entry: LogEntry = {
      level,
      message,
      timestamp: new Date().toISOString(),
      context,
      error,
    }

    const formatted = this.formatEntry(entry)

    switch (level) {
      case 'debug':
        console.debug(formatted)
        break
      case 'info':
        console.info(formatted)
        break
      case 'warn':
        console.warn(formatted)
        break
      case 'error':
        console.error(formatted)
        break
    }
  }

  debug(message: string, context?: Record<string, unknown>) {
    this.log('debug', message, context)
  }

  info(message: string, context?: Record<string, unknown>) {
    this.log('info', message, context)
  }

  warn(message: string, context?: Record<string, unknown>) {
    this.log('warn', message, context)
  }

  error(message: string, error?: Error, context?: Record<string, unknown>) {
    this.log('error', message, context, error)
  }
}

export const logger = new Logger()

