class Backup
  include UrlHelper
  include ActiveModel::SerializerSupport

  attr_reader :filename
  attr_accessor :size, :path, :link

  def initialize(filename)
    @filename = filename
  end

  def self.all
    Dir.glob(File.join(Backup.base_directory, "*.tar.gz"))
       .sort_by { |file| File.mtime(file) }
       .reverse
       .map { |backup| Backup.create_from_filename(File.basename(backup)) }
  end

  def self.[](filename)
    path = File.join(Backup.base_directory, filename)
    if File.exists?(path)
      Backup.create_from_filename(filename)
    else
      nil
    end
  end

  def remove
    File.delete(@path) if File.exists?(path)
    after_remove_hook
  end

  def after_create_hook
    upload_to_s3 if SiteSetting.enable_s3_backups?
  end

  def after_remove_hook
    remove_from_s3 if SiteSetting.enable_s3_backups?
  end

  def upload_to_s3
    return unless fog_directory
    fog_directory.files.create(key: @filename, public: false, body: File.read(@path))
  end

  def remove_from_s3
    return unless fog
    fog.delete_object(SiteSetting.s3_backup_bucket, @filename)
  end

  def self.base_directory
    File.join(Rails.root, "public", "backups", RailsMultisite::ConnectionManagement.current_db)
  end

  def self.chunk_path(identifier, filename, chunk_number)
    File.join(Backup.base_directory, "tmp", identifier, "#{filename}.part#{chunk_number}")
  end

  def self.create_from_filename(filename)
    Backup.new(filename).tap do |b|
      b.path = File.join(Backup.base_directory, b.filename)
      b.link = b.schemaless "#{Discourse.base_url}/admin/backups/#{b.filename}"
      b.size = File.size(b.path)
    end
  end

  def self.remove_old
    all_backups = Backup.all
    return unless all_backups.size > SiteSetting.maximum_backups
    all_backups[SiteSetting.maximum_backups..-1].each(&:remove)
  end

  private

    def s3_options
      {
        provider: 'AWS',
        aws_access_key_id: SiteSetting.s3_access_key_id,
        aws_secret_access_key: SiteSetting.s3_secret_access_key,
        region: SiteSetting.s3_region.blank? ? "us-east-1" : SiteSetting.s3_region,
      }
    end

    def fog
      return @fog if @fog
      return unless SiteSetting.s3_access_key_id.present? &&
                    SiteSetting.s3_secret_access_key.present? &&
                    SiteSetting.s3_backup_bucket.present?
      require 'fog'
      @fog = Fog::Storage.new(s3_options)
    end

    def fog_directory
      return @fog_directory if @fog_directory
      return unless fog
      @fog_directory ||= fog.directories.get(SiteSetting.s3_backup_bucket)
    end

end