/**
 * AbstractLogger
 *
 * Defines the shared logging interface for concrete loggers.
 */
class AbstractLogger {
  info() {
    throw new Error('info must be implemented by subclasses')
  }

  error() {
    throw new Error('error must be implemented by subclasses')
  }
}

/**
 * ConsoleLogger
 *
 * Writes structured logs to stdout and stderr.
 */
class ConsoleLogger extends AbstractLogger {
  /**
   * @param {string} message
   * @param {object} [context]
   * @returns {void}
   */
  info(message, context = {}) {
    console.log(JSON.stringify({ level: 'info', message, context, timestamp: new Date().toISOString() }))
  }

  /**
   * @param {string} message
   * @param {Error | object} [error]
   * @returns {void}
   */
  error(message, error = {}) {
    console.error(JSON.stringify({ level: 'error', message, error: this._normalizeError(error), timestamp: new Date().toISOString() }))
  }

  /**
   * @param {Error | object} error
   * @returns {object}
   */
  _normalizeError(error) {
    if (error instanceof Error) {
      return {
        name: error.name,
        message: error.message,
        stack: error.stack
      }
    }
    return error
  }
}

module.exports = {
  AbstractLogger,
  ConsoleLogger
}