# frozen_string_literal: true

module Tmm
  class FileService
    def self.add(doc:, file:, kind:, downloadable: nil)
      user = User.find_by(email: doc['depositor_tesim'].first)
      monograph = Monograph.find(doc.id)
      uploaded_file = Hyrax::UploadedFile.create(file: File.new(file), user: user)
      attrs = {}
      attrs[:import_uploaded_files_ids] = [uploaded_file.id]
      attrs[:import_uploaded_files_attributes] = [files_attributes(kind, downloadable)]
      Hyrax::CurationConcern.actor.update(Hyrax::Actors::Environment.new(monograph, Ability.new(user), attrs))
    end

    def self.replace(file_set_id:, new_file_path:)
      file_set = FileSet.find file_set_id

      # Eradicate all Files from the FileSet a.k.a. delete all the file versions and their tombstones from Fedora
      file_set.files.each do |file|
        file.delete(eradicate: true)
      end

      # Reload the FileSet with all files eradicated a.k.a. file_set.files.blank? === true.
      file_set = FileSet.find file_set_id

      # Cleanup the FileSet metadata
      now = Hyrax::TimeService.time_in_utc
      file_set.date_uploaded = now
      file_set.date_modified = now
      file_set.label = File.basename(new_file_path)
      file_set.title = [File.basename(new_file_path)]
      file_set.save!

      # Add the new file
      Hydra::Works::AddFileToFileSet.call(file_set, File.open(new_file_path), :original_file)

      # Queue Characterize Job
      CharacterizeJob.perform_later(file_set, file_set.original_file.id)
    end

    def self.replace?(file_set_id:, new_file_path:)
      presenter = Hyrax::PresenterFactory.build_for(ids: [file_set_id], presenter_class: Hyrax::FileSetPresenter, presenter_args: nil).first
      return false if presenter.blank?
      return false if presenter.original_checksum.blank?

      # it might seem a bit messy to raise an exception here, but this should be a rare occurrence, plus it's...
      # something that does require immediate investigation and only affects rake tasks right now
      raise "The FileSet #{file_set_id} does not match the type of the new file." if mismatched_types?(new_file_path, presenter)

      # always allow replacement if the type is OK and the filenames differ, i.e. we allow the renaming of a file
      return true if File.basename(new_file_path) != presenter.original_name.first

      # The original file_set checksum we're using has been generated by Fedora,
      # not ActiveFedora or anything in the Samvera ruby stack (that I can tell...).
      # I imagine this is fine since an MD5 is an MD5 the world around.
      return false if Digest::MD5.file(new_file_path).hexdigest == presenter.original_checksum.first
      true
    end

    def self.mismatched_types?(new_file_path, presenter) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
      # sticking to images and ebook types that have actually been replaced using associated rake tasks
      return true if presenter.probable_image? && %w[.bmp .gif .jp2 .jpeg .jpg .png .tif .tiff].exclude?(File.extname(new_file_path).downcase)
      return true if presenter.epub? && '.epub' != File.extname(new_file_path).downcase
      return true if presenter.pdf? && '.pdf' != File.extname(new_file_path).downcase
      # one full-book mp3 file, or a zip which contains several mp3 files, e.g. one per chapter/section
      return true if presenter.audiobook? && %w[.mp3 .zip].exclude?(File.extname(new_file_path).downcase)
      false
    end

    def self.files_attributes(kind, ebooks_downloadable = nil) # rubocop:disable Metrics/CyclomaticComplexity
      attrs = case kind
              when :cover
                { representative_kind: 'cover' }
              when :epub
                { representative_kind: 'epub' }
              when :pdf
                { representative_kind: 'pdf_ebook' }
              when :audiobook
                { representative_kind: 'audiobook' }
              end
      ebooks_downloadable && [:epub, :pdf, :audiobook].include?(kind) ? attrs.merge({ allow_download: 'yes' }) : attrs
    end
  end
end
