require 'logger'
require 'time'

module Pallets
  class Logger < ::Logger
    # Overwrite severity methods to add metadata capabilities
    %i[debug info warn error fatal unknown].each do |severity|
      define_method severity do |message|
        metadata = Thread.current[:pallets_log_metadata]
        return super(message) if metadata.nil?

        super(metadata) { message }
      end
    end

    def with_metadata(hash)
      Thread.current[:pallets_log_metadata] = hash
      yield
    ensure
      Thread.current[:pallets_log_metadata] = nil
    end

    module Formatters
      class Pretty < ::Logger::Formatter
        def call(severity, time, metadata, message)
          formatted_metadata = ' ' + metadata.map { |k, v| "#{k}=#{v}" }.join(' ') if metadata
          "#{time.utc.iso8601(4)} pid=#{Process.pid}#{formatted_metadata} #{severity}: #{message}\n"
        end
      end

      class Json < ::Logger::Formatter
        def call(severity, time, metadata, message)
          {
            timestamp: time.utc.iso8601(4),
            pid: Process.pid,
            severity: severity,
            message: message
          }.merge(metadata || {}).to_json + "\n"
        end
      end
    end
  end
end
