import { Injectable } from '@angular/core';
import { LogLevel } from './log-level.enum';
import { Sink, LoggerContext } from './logging.types';

/**
 * A sink implementation that outputs logs to the browser console.
 * This is the primary logging destination for development environments.
 *
 * The sink maps each log level to the appropriate console method:
 * - Trace → console.trace (with stack trace)
 * - Debug → console.debug
 * - Info → console.info
 * - Warn → console.warn
 * - Error → console.error
 *
 * Context data and error objects are passed as additional arguments to provide
 * rich debugging information in the browser developer tools.
 *
 * @example
 * ```typescript
 * // Configure in app initialization
 * provideLogging(
 *   withLogLevel(LogLevel.Debug),
 *   withSink(ConsoleLogSink)
 * );
 * ```
 */
@Injectable()
export class ConsoleLogSink implements Sink {
  /**
   * Logs a message to the browser console with the appropriate log level.
   * The console method used depends on the log level, and context/error data
   * is passed as additional arguments for improved debugging experience.
   *
   * @param level - The severity level of the log message
   * @param message - The main log message content
   * @param context - Optional structured data or metadata about the log event
   * @param error - Optional error object when logging errors
   *
   * @example
   * ```typescript
   * const sink = new ConsoleLogSink();
   * sink.log(LogLevel.Info, 'User logged in', { userId: '123' });
   * sink.log(LogLevel.Error, 'API failed', { endpoint: '/users' }, new Error('Network error'));
   * ```
   */
  log(
    level: LogLevel,
    message: string,
    context?: LoggerContext,
    error?: Error,
  ): void {
    switch (level) {
      case LogLevel.Trace:
        if (context) {
          console.trace(message, context);
        } else {
          console.trace(message);
        }
        break;
      case LogLevel.Debug:
        if (context) {
          console.debug(message, context);
        } else {
          console.debug(message);
        }
        break;
      case LogLevel.Info:
        if (context) {
          console.info(message, context);
        } else {
          console.info(message);
        }
        break;
      case LogLevel.Warn:
        if (context) {
          console.warn(message, context);
        } else {
          console.warn(message);
        }
        break;
      case LogLevel.Error:
        if (error) {
          if (context) {
            console.error(message, error, context);
          } else {
            console.error(message, error);
          }
        } else if (context) {
          console.error(message, context);
        } else {
          console.error(message);
        }
        break;
      // LogLevel.Off - no logs will be sent to this sink
    }
  }
}
