require 'rails_helper'

RSpec.describe RemoteStorageAuthorization, type: :model do
  include ActiveJob::TestHelper

  let(:user) { create :user }

  describe "#create" do
    after(:each) { clear_enqueued_jobs }
    after(:all)  { redis_rs_delete_keys("rs:authorizations:*") }

    let(:auth) do
      user.remote_storage_authorizations.create!(
        permissions: %w(documents photos contacts:rw videos:r tasks/work:r),
        client_id: "example.com",
        redirect_uri: "https://example.com"
      )
    end

    it "generates a token" do
      expect(auth.token).to match(/[a-zA-Z0-9]+/)
    end

    it "stores a token in redis" do
      user_auth_keys = redis_rs.keys("rs:authorizations:#{user.address}:*")
      expect(user_auth_keys.length).to eq(1)

      authorizations = redis_rs.smembers(user_auth_keys.first)
      expect(authorizations.sort).to eq(%w(documents photos contacts:rw videos:r tasks/work:r).sort)
    end

    context "with expiry set" do
      it "enqueues an expiration job" do
        auth_with_expiry = user.remote_storage_authorizations.create!(
          permissions: %w(documents:rw), client_id: "example.com",
          redirect_uri: "https://example.com",
          expire_at: 1.month.from_now
        )
        job = enqueued_jobs.select{|j| j['job_class'] == "RemoteStorageExpireAuthorizationJob"}.first
        expect(job['arguments'][0]).to eq(auth_with_expiry.id)
      end
    end
  end

  describe "#destroy" do
    after(:each) { clear_enqueued_jobs }
    after(:all)  { redis_rs_delete_keys("rs:authorizations:*") }

    it "removes the token from redis" do
      auth = user.remote_storage_authorizations.create!(
               permissions: %w(shares:rw documents pictures:r),
               client_id: "sharesome.5apps.com",
               redirect_uri: "https://sharesome.5apps.com"
             )
      auth.destroy!

      expect(redis_rs.keys("rs:authorizations:#{user.address}:*")).to be_empty
    end

    context "with expiry set" do
      it "removes the expiration job" do
        auth_with_expiry = user.remote_storage_authorizations.create!(
          permissions: %w(documents:rw), client_id: "example.com",
          redirect_uri: "https://example.com",
          expire_at: 1.month.from_now
        )
        # Cannot test for removal from the actual Sidekiq::Queue, because it is
        # not used in specs, but the method directly removes jobs from there
        expect(auth_with_expiry).to receive(:remove_token_expiry_job)
        auth_with_expiry.destroy!
      end
    end
  end

  # describe "#find_or_create_web_app" do
  #   context "with origin that looks hosted" do
  #     before do
  #       auth = user.remote_storage_authorizations.create!(
  #                 permissions: %w(documents photos contacts:rw videos:r tasks/work:r),
  #                 client_id: "example.com",
  #                 redirect_uri: "https://example.com",
  #                 expire_at: 1.month.from_now
  #               )
  #     end
  #
  #     it "generates a web_app" do
  #       expect(auth.web_app).to be_a(AppCatalog::WebApp)
  #     end
  #
  #     it "uses the Web App's name as app name" do
  #       expect(auth.app_name).to eq("Example Domain")
  #     end
  #   end
  #
  #   context "when creating two authorizations for the same app" do
  #     before do
  #       user_2 = create :user
  #       ResqueSpec.reset!
  #       auth_1 = user.remote_storage_authorizations.create!(
  #                 permissions: %w(documents photos contacts:rw videos:r tasks/work:r),
  #                 client_id: "example.com",
  #                 redirect_uri: "https://example.com",
  #                 expire_at: 1.month.from_now
  #               )
  #       auth_2 = user_2.remote_storage_authorizations.create!(
  #                 permissions: %w(documents photos contacts:rw videos:r tasks/work:r),
  #                 client_id: "example.com",
  #                 redirect_uri: "https://example.com",
  #                 expire_at: 1.month.from_now
  #               )
  #     end
  #
  #     after do
  #       auth_1.destroy
  #       auth_2.destroy
  #       user_2.destroy
  #     end
  #
  #     it "uses the same web app instance for both authorizations" do
  #       expect(auth_1.web_app).to be_a(AppCatalog::WebApp)
  #       expect(auth_1.web_app).to eq(auth_2.web_app)
  #     end
  #   end
  #
  #   describe "non-production app origins" do
  #     context "when host is not an FQDN" do
  #       before do
  #         auth = user.remote_storage_authorizations.create!(
  #                   permissions: %w(recipes),
  #                   client_id: "localhost:4200",
  #                   redirect_uri: "http://localhost:4200"
  #                 )
  #       end
  #
  #       it "does not create a web app" do
  #         expect(auth.web_app).to be_nil
  #         expect(auth.app_name).to eq("localhost:4200")
  #       end
  #     end
  #
  #     context "when host is an IP address" do
  #       before do
  #         auth = user.remote_storage_authorizations.create!(
  #                   permissions: %w(recipes),
  #                   client_id: "192.168.0.23:3000",
  #                   redirect_uri: "http://192.168.0.23:3000"
  #                 )
  #       end
  #
  #       it "does not create a web app" do
  #         expect(auth.web_app).to be_nil
  #         expect(auth.app_name).to eq("192.168.0.23:3000")
  #       end
  #     end
  #
  #     context "when host is an extension URL" do #       before do
  #         auth = user.remote_storage_authorizations.create!(
  #                   permissions: %w(bookmarks),
  #                   client_id: "123.addons.allizom.org",
  #                   redirect_uri: "123.addons.allizom.org/foo"
  #                 )
  #       end
  #
  #       it "does not create a web app" do
  #         expect(auth.web_app).to be_nil
  #         expect(auth.app_name).to eq("123.addons.allizom.org")
  #       end
  #     end
  #   end
  # end

  # describe "auth notifications" do
  #   context "with auth notifications enabled" do
  #     before do
  #       ResqueSpec.reset!
  #       user.push(mailing_lists: "rs-auth-notifications-#{Rails.env}")
  #       auth = user.remote_storage_authorizations.create!(
  #                 :permissions => %w(documents photos contacts:rw videos:r tasks/work:r),
  #                 :client_id => "example.com",
  #                 :redirect_uri => "https://example.com"
  #               )
  #     end
  #
  #     it "notifies the user via email" do
  #       expect(enqueued_jobs.size).to eq(1)
  #       job = enqueued_jobs.first
  #       expect(job).to eq(
  #         job: ActionMailer::DeliveryJob,
  #         args: ['StorageAuthorizationMailer', 'authorized_rs_app', 'deliver_now',
  #                auth.id.to_s],
  #         queue: 'mailers'
  #       )
  #     end
  #   end
  #
  #   context "with auth notifications disabled" do
  #     before do
  #       ResqueSpec.reset!
  #       user.pull(mailing_lists: "rs-auth-notifications-#{Rails.env}")
  #       auth = user.remote_storage_authorizations.create!(
  #                 :permissions => %w(documents photos contacts:rw videos:r tasks/work:r),
  #                 :client_id => "example.com",
  #                 :redirect_uri => "https://example.com"
  #               )
  #     end
  #
  #     it "does not notify the user via email about new RS app" do
  #       expect(enqueued_jobs.size).to eq(0)
  #     end
  #   end
  # end
end
