# frozen_string_literal: true

# Persist an ImportRequestAttempt-body if prerequisits are met
class PersistResponseBody
  ACCEPTED_APPLICATION_TYPES = %w[json xml].freeze

  def self.call(**args)
    new(**args).call
  end

  def initialize(attempt:, body:, headers:)
    @attempt = attempt
    @body    = body
    @headers = headers
  end

  attr_reader :attempt, :body, :headers

  def call
    prerequisites_not_met = check_prerequisites

    if prerequisites_not_met
      Rails.logger.debug("Won't persist body: #{prerequisites_not_met}")
    else
      persist
    end
  end

  private

  def check_prerequisites
    catch(:not_met) do
      check_environment
      check_body
      check_headers
    end
  end

  def check_body
    throw :not_met, 'body is not encoded correctly' unless body.valid_encoding?
    throw :not_met, 'body is blank' if body.blank?
  end

  def check_environment
    persistence_wanted = ENV['PERSIST_IMPORT_REQUEST_BODIES']
    return if ActiveModel::Type::Boolean.new.cast(persistence_wanted)

    throw :not_met, "$PERSIST_IMPORT_REQUEST_BODIES is set to #{persistence_wanted || 'nil'}"
  end

  def check_headers
    throw :not_met, 'unable to determint content-type' unless content_type

    return if content_type.match?(%r{\Atext/})

    match = content_type.match(%r{\Aapplication/([A-Za-z0-9*-]+)})
    throw :not_met, %(content-type "#{content_type}" not allowed) \
      unless match && ACCEPTED_APPLICATION_TYPES.include?(match[1])
  end

  def content_type
    headers['content-type']
  end

  def persist
    attempt.create_body!(content: body)
  end
end
