module ErrorsHelper
  # Displays an alert containing a list of error messages for a given model attribute
  def errors_for(model, attribute)
    ErrorsList.new(self, model, attribute).to_html
  end

  # Displays an alert containing a list of all the error messages for a given model
  def errors_summary_for(model)
    ErrorsSummary.new(self, model).to_html
  end

  private

  class ErrorsList
    def initialize(view, model, attribute)
      @view = view
      @model = model
      @attribute = attribute
    end

    def to_html
      return if errors.empty?

      error_list_items = errors.map { |error| content_tag(:li, error) }

      content_tag(:div, class: "alert alert-danger text-left") do
        concat content_tag(:p, message)
        concat content_tag(:ul, safe_join(error_list_items))
      end
    end

    private

    attr_reader :view, :model, :attribute

    delegate :concat, :content_tag, :safe_join, to: :view

    def errors
      @errors ||= errors = model.errors[attribute]
    end

    def message
      "#{attribute.to_s.humanize} is not valid."
    end
  end

  class ErrorsSummary
    def initialize(view, model)
      @view = view
      @model = model
    end

    def to_html
      return if errors.empty?

      content_tag(:div, class: "alert alert-danger text-left") do
        concat content_tag(:p, translate("errors_helper.failure_message", model_name: name))
        concat content_tag(:ul, safe_join(error_list_items))
      end
    end

    private

    attr_reader :view, :model

    delegate :concat, :content_tag, :safe_join, :translate, to: :view

    def errors
      @errors ||= model.errors.full_messages
    end

    def error_list_items
      errors.map { |error| content_tag(:li, error) }
    end

    def name
      model.model_name.human.downcase
    end
  end
end
