class S3BackupService < BackupService
  attr_reader :client, :bucket

  def initialize(client: nil, bucket: Danbooru.config.aws_s3_bucket_name)
    @credentials = Aws::Credentials.new(Danbooru.config.aws_access_key_id, Danbooru.config.aws_secret_access_key)
    @client = client || Aws::S3::Client.new(credentials: @credentials, region: "us-east-1", logger: Logger.new(STDOUT))
    @bucket = bucket
  end

  def backup(file_path, type: nil, **options)
    keys = s3_keys(file_path, type)
    keys.each do |key|
      upload_to_s3(key, file_path)
    end
  end

  def delete(file_path, type: nil)
    keys = s3_keys(file_path, type)
    keys.each do |key|
      delete_from_s3(key)
    end
  end

protected
  def s3_keys(file_path, type)
    name = File.basename(file_path)

    case type
    when :original
      [name]
    when :preview
      ["preview/#{name}", "cropped/small/#{name}", "cropped/large/#{name}"]
    when :large
      ["sample/#{name}"]
    else
      raise ArgumentError.new("Unknown type: #{type}")
    end
  end

  def delete_from_s3(key)
    client.delete_object(bucket: bucket, key: key)
  rescue Aws::S3::Errors::NoSuchKey
    # ignore
  end

  def upload_to_s3(key, file_path)
    File.open(file_path, "rb") do |body|
      base64_md5 = Digest::MD5.base64digest(File.read(file_path))
      client.put_object(acl: "public-read", bucket: bucket, key: key, body: body, content_md5: base64_md5)
    end
  end
end
