# frozen_string_literal: true

# Import an image from coverartarchive.org
class ImportCoverArtImage
  def self.call(**args)
    new(**args).call
  end

  def initialize(import_order:, metadata:, target_object:)
    @import_order  = import_order
    @metadata      = kleinodify_metadata(metadata)
    @target_object = target_object
  end

  attr_reader :import_order,  :metadata, :target_object

  def find_existing
    Image.find_by(coverartarchive_code: metadata[:code])
  end

  def call
    target_object.assign_attributes(target_attributes)

    target_object.save!

    add_tags

    target_object
  end

  private

  def add_tags
    tags = metadata[:tags] || return

    tags.each do |tag_name|
      target_object.tags << ImageTag.find_or_create_by_name(tag_name)
    end

    target_object.save!
  end

  def create_image
    code = metadata[:code]
    image = Image.create!(coverartarchive_code: code, import_order: import_order)
    image.file.attach(io: image_io, filename: "coverartarchiveorg_#{code}")

    image.save!

    image
  end

  def fetch_image
    CoverArtArchiveApi.get(import_order: import_order, uri: uri).body
  rescue ImportError::CanNotFetch => e
    Rails.logger.error(e)
    nil
  end

  def image
    @image ||= create_image
  end

  def image_io
    body = fetch_image || return

    @image_io = StringIO.new(body)
  end

  # This method smells of :reek:FeatureEnvy
  def kleinodify_metadata(metadata)
    {
      back_cover:   metadata[:back],
      code:         metadata[:id],
      front_cover:  metadata[:front],
      image:        metadata[:image],
      import_order: import_order,
      note:         metadata[:comment],
      tags:         metadata[:types]
    }
  end

  def target_attributes
    {
      back_cover:   metadata[:back_cover],
      front_cover:  metadata[:front_cover],
      image:        image,
      import_order: import_order,
      note:         metadata[:note]
    }
  end

  def uri
    metadata[:image]
  end
end
