# lib/log.rb
# Minimal structured logger for the scraping pipeline.
#
# Usage:
#   require_relative "log"
#   Log.info  "geocode", "geocoded DA0306/2025 -> 42 Main St, Hobart"
#   Log.warn  "enrich",  "lookup failed for da_foo DA123: connection refused"
#   Log.debug "migrate", "column address_std already exists — skipped"
#   Log.error "db",      "prepare failed: unknown column 'foo'"
#
# Output format (no timestamp — Docker/systemd adds one):
#   INFO  [geocode] geocoded DA0306/2025 -> 42 Main St, Hobart
#   WARN  [enrich]  lookup failed for da_foo DA123: connection refused
#
# Verbosity is controlled by the LOG_LEVEL environment variable:
#   LOG_LEVEL=debug  — all messages
#   LOG_LEVEL=info   — info, warn, error          (default)
#   LOG_LEVEL=warn   — warn and error only
#   LOG_LEVEL=error  — errors only
#
# INFO and DEBUG go to $stdout; WARN and ERROR go to $stderr so that
# docker compose logs shows them on the correct stream.

module Log
  LEVELS = { debug: 0, info: 1, warn: 2, error: 3 }.freeze

  # Flush immediately — important in Docker where stdout may be block-buffered.
  $stdout.sync = true
  $stderr.sync = true

  def self.debug(component, msg) = emit(:debug, component, msg)
  def self.info(component, msg)  = emit(:info,  component, msg)
  def self.warn(component, msg)  = emit(:warn,  component, msg)
  def self.error(component, msg) = emit(:error, component, msg)

  # ---------------------------------------------------------------------------

  def self.min_level
    key = ENV.fetch("LOG_LEVEL", "info").strip.downcase.to_sym
    LEVELS.fetch(key, LEVELS[:info])
  end
  private_class_method :min_level

  def self.emit(level, component, msg)
    return if LEVELS.fetch(level) < min_level
    label  = level.to_s.upcase.ljust(5)
    stream = (level == :debug || level == :info) ? $stdout : $stderr
    stream.puts "#{label} [#{component}] #{msg}"
  end
  private_class_method :emit
end
