// src/services/logger.ts

export enum LogLevel {
  ERROR = 0,
  WARN = 1,
  INFO = 2,
  DEBUG = 3
}

interface LogContext {
  [key: string]: any;
}

class Logger {
  private logLevel: LogLevel;
  private enabledContexts: Set<string>;

  constructor() {
    this.logLevel = this.getLogLevel();
    this.enabledContexts = this.getEnabledContexts();
  }

  private getLogLevel(): LogLevel {
    const level = process.env.LOG_LEVEL?.toUpperCase() || 'INFO';
    switch (level) {
      case 'ERROR': return LogLevel.ERROR;
      case 'WARN': return LogLevel.WARN;
      case 'DEBUG': return LogLevel.DEBUG;
      default: return LogLevel.INFO;
    }
  }

  private getEnabledContexts(): Set<string> {
    const contexts = process.env.LOG_CONTEXTS?.split(',') || [];
    return new Set(contexts.map(c => c.trim().toLowerCase()));
  }

  private shouldLog(level: LogLevel, context: string): boolean {
    if (level > this.logLevel) return false;
    if (this.enabledContexts.size > 0 && !this.enabledContexts.has(context.toLowerCase())) {
      return false;
    }
    return true;
  }

  private formatMessage(level: string, context: string, message: string, data?: LogContext): string {
    const timestamp = new Date().toISOString();
    const contextStr = context.toUpperCase().padEnd(12);
    let logMessage = `[${timestamp}] ${level.padEnd(5)} [${contextStr}] ${message}`;
    
    if (data && Object.keys(data).length > 0) {
      const dataStr = Object.entries(data)
        .map(([key, value]) => `${key}=${typeof value === 'object' ? JSON.stringify(value) : value}`)
        .join(' ');
      logMessage += ` | ${dataStr}`;
    }
    
    return logMessage;
  }

  error(context: string, message: string, error?: Error, data?: LogContext): void {
    if (!this.shouldLog(LogLevel.ERROR, context)) return;
    
    const logData = { ...data };
    if (error) {
      logData.error = error.message;
      logData.stack = error.stack;
    }
    
    console.error(this.formatMessage('ERROR', context, message, logData));
  }

  warn(context: string, message: string, data?: LogContext): void {
    if (!this.shouldLog(LogLevel.WARN, context)) return;
    console.warn(this.formatMessage('WARN', context, message, data));
  }

  info(context: string, message: string, data?: LogContext): void {
    if (!this.shouldLog(LogLevel.INFO, context)) return;
    console.log(this.formatMessage('INFO', context, message, data));
  }

  debug(context: string, message: string, data?: LogContext): void {
    if (!this.shouldLog(LogLevel.DEBUG, context)) return;
    console.log(this.formatMessage('DEBUG', context, message, data));
  }

  // Specialized logging methods for common contexts
  pipeline(phase: string, action: string, details?: LogContext): void {
    this.info('pipeline', `${phase}/${action}`, details);
  }

  audit(phase: string, action: string, confidence: number, timeMs: number, metadata?: LogContext): void {
    this.info('audit', `${phase}/${action} completed`, {
      confidence: `${confidence}%`,
      duration: `${timeMs}ms`,
      ...metadata
    });
  }

  api(method: string, path: string, status: number, details?: LogContext): void {
    const level = status >= 400 ? LogLevel.ERROR : status >= 300 ? LogLevel.WARN : LogLevel.INFO;
    if (level === LogLevel.ERROR) {
      this.error('api', `${method} ${path}`, undefined, { status, ...details });
    } else if (level === LogLevel.WARN) {
      this.warn('api', `${method} ${path}`, { status, ...details });
    } else {
      this.info('api', `${method} ${path}`, { status, ...details });
    }
  }

  embedding(action: string, details?: LogContext): void {
    this.info('embedding', action, details);
  }

  selection(method: string, toolCount: number, conceptCount: number, details?: LogContext): void {
    this.info('selection', `${method} selection completed`, {
      tools: toolCount,
      concepts: conceptCount,
      ...details
    });
  }

  confidence(toolName: string, overall: number, semantic: number, suitability: number): void {
    this.debug('confidence', `${toolName} scored`, {
      overall: `${overall}%`,
      semantic: `${semantic}%`,
      suitability: `${suitability}%`
    });
  }

  queue(action: string, details?: LogContext): void {
    this.info('queue', action, details);
  }

  // Performance timing
  time(context: string, label: string): string {
    const timerId = `${context}:${label}:${Date.now()}`;
    console.time(timerId);
    return timerId;
  }

  timeEnd(timerId: string, message?: string): void {
    console.timeEnd(timerId);
    if (message) {
      const [context] = timerId.split(':');
      this.debug(context, message);
    }
  }
}

export const logger = new Logger();

// Export convenience functions for common patterns
export const logPipeline = logger.pipeline.bind(logger);
export const logAudit = logger.audit.bind(logger);
export const logAPI = logger.api.bind(logger);
export const logError = logger.error.bind(logger);
export const logInfo = logger.info.bind(logger);