# typed: true
module HasMeasureDuration
  extend T::Sig
  extend T::Helpers
  abstract!

  requires_ancestor { HasColorLogger }

  sig { abstract.returns(ColorLogger) }
  def logger
  end

  sig do
    type_parameters(:U)
      .params(
        title:
          T.any(
            String,
            T
              .proc
              .params(
                arg0: T.nilable(T.type_parameter(:U)),
                duration: T.nilable(Numeric),
              )
              .returns(String),
          ),
        block: T.proc.returns(T.type_parameter(:U)),
      )
      .returns(T.type_parameter(:U))
  end
  def measure(title, &block)
    now = Time.now
    title_str = title.is_a?(Proc) && title.call(nil, nil) || title
    logger.info "[start]  #{title_str}"
    ret = yield
    duration = Time.now - now
    if duration >= 1.hour
      duration_str = "#{(duration / 1.hour).round(2).to_s.bold} hr"
    elsif duration >= 5.minute
      duration_str = "#{(duration / 1.minute).round(2).to_s.bold} min"
    elsif duration >= 5.second
      duration_str = "#{duration.round(2).to_s.bold} sec"
    else
      duration_str = "#{(duration * 1000).round(0).to_s.bold} ms"
    end
    title_str = title.is_a?(Proc) && title.call(ret, duration) || title
    logger.info "[finish] #{title_str} - #{duration_str}"
    ret
  end
end
