require 'digest'
require 'json'

class MaterialFileSha256
  def self.blob_metadata blob
    metadata = blob.metadata
    return metadata if metadata.is_a?(Hash)
    return { } if metadata.blank?

    JSON.parse(metadata)
  rescue JSON::ParserError
    { }
  end

  def self.metadata_sha256 blob
    blob_metadata(blob)['sha256'].presence
  end

  def self.assign_metadata_sha256! blob, sha256
    return if sha256.blank?

    metadata = blob_metadata(blob)
    metadata['sha256'] = sha256
    blob.metadata = metadata
    blob.save! if blob.changed?
  end

  def self.from_blob blob, allow_download: false
    sha256 = metadata_sha256(blob)
    return sha256 if sha256.present?
    return nil unless allow_download

    begin
      blob.open do |file|
        sha256 = Digest::SHA256.file(file.path).hexdigest
        assign_metadata_sha256!(blob, sha256)
        sha256
      end
    rescue ActiveStorage::FileNotFoundError, ArgumentError => error
      Rails.logger.warn(
          "MaterialFileSha256.from_blob failed for blob_id=#{blob.id}: " \
          "#{error.class}: #{error.message}",
      )
      nil
    end
  end

  def self.from_upload upload
    tempfile = upload&.tempfile
    return nil unless tempfile

    tempfile.rewind
    Digest::SHA256.file(tempfile.path).hexdigest.tap do
      tempfile.rewind
    end
  end
end
