require "spec_helper"

describe G5Updatable::ClientFeedProcessor do
  let(:token) { 'a-token' }

  describe ".new" do
    let(:params) { {client_uid: passed_uid} }
    let(:processor) { described_class.new params }
    subject(:client_uid) { processor.client_uid }
    let(:configured_client_uid) { nil }

    context "when CLIENT_UID is unset" do
      context "with a passed-in client_uid" do
        let(:passed_uid) { "passed" }
        it { should eq("passed") }
      end

      context "with no passed-in client_uid" do
        let(:passed_uid) { nil }

        it "explodes helpfully" do
          expect { client_uid }.to raise_error(/client_uid/)
        end
      end
    end

    context "when CLIENT_UID is set" do
      before do
        @old_client_uid   = ENV["CLIENT_UID"]
        ENV["CLIENT_UID"] = "configured"
      end
      after { ENV["CLIENT_UID"] = @old_client_uid }

      context "with a passed-in client_uid" do
        let(:passed_uid) { "passed" }
        it { should eq("passed") }
      end

      context "with no passed-in client_uid" do
        let(:passed_uid) { nil }
        it { should eq("configured") }
      end
    end
  end

  describe '#load_all_clients' do
    before do
      allow(G5Updatable::Fetcher).to receive(:do_with_username_pw_access_token).and_yield(token)
      stub_request(:get, 'https://g5-hub.herokuapp.com/urns.json?access_token=a-token').
          with(:headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).
          to_return(status: 200, body: fixture('urns.json'), headers: {})
    end

    it 'loads each client' do
      expect(G5Updatable::ClientFeedProcessor).to receive(:new).with(client_uid: 'https://g5-hub.herokuapp.com/clients/g5-c-iwcqdt3u-arenhall-management-company-client.json')
      expect(G5Updatable::ClientFeedProcessor).to receive(:new).with(client_uid: 'https://g5-hub.herokuapp.com/clients/g5-c-iw2fm3cx-artis-senior-living-management-multidomain.json')
      G5Updatable::ClientFeedProcessor.load_all_clients
    end
  end

  describe '#work', integration: true do
    let(:client_uid) { 'http://hub.g5dxm.com/clients/g5-c-1soj8m6e-g5-multifamily' }
    let(:location_uid) { 'http://hub.g5dxm.com/clients/g5-c-1soj8m6e-g5-multifamily/locations/g5-cl-1soj9pe2-541-apartments' }

    context 'just client_uid' do
      subject { described_class.new(client_uid: client_uid) }
      before do
        allow(G5Updatable::Fetcher).to receive(:do_with_username_pw_access_token).and_yield(token)
        stub_request(:get, "#{client_uid}?access_token=#{token}").
            with(:headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).
            to_return(status: 200, body: fixture('client-g5-c-1soj8m6e-g5-multifamily.json'), headers: {})
      end

      let(:created_client) { G5Updatable::Client.last }

      it 'creates a client' do
        expect { subject.work }.to change { G5Updatable::Client.count }.by(1)
        expect(created_client.urn).to eq('g5-c-1soj8m6e-g5-multifamily')
      end

      it 'creates locations' do
        expect { subject.work }.to change { G5Updatable::Location.count }.by(5)
        expect(created_client.locations.collect(&:urn)).to match_array(%w(g5-cl-1soj9pe2-541-apartments g5-cl-1soja3fn-99-apartments g5-cl-560belmk8-denali g5-cl-i2xqm52t-mockup-design-3 g5-cl-i2gg3rv8-g5-apartments))
      end

      it 'creates amenities' do
        expect { subject.work }.to change { G5Updatable::HubAmenity.count }.by(2)
        expect(G5Updatable::HubAmenity.all.collect(&:name)).to match_array(['WIFI', 'Power'])
        expect(G5Updatable::Location.find_by_urn('g5-cl-560belmk8-denali').hub_amenities.collect(&:name)).to match_array(['WIFI', 'Power'])
      end

      context 'subsequent update with missing locations' do
        before do
          subject.work
          expect(created_client.locations.count).to eq(5)
          stub_request(:get, "#{client_uid}?access_token=#{token}").
              with(:headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).
              to_return(status: 200, body: fixture('client-g5-c-1soj8m6e-g5-multifamily-missing-locations.json'), headers: {})
        end

        it 'removes orphaned locations' do
          expect { subject.work }.to change { created_client.locations.count }.from(5).to(1)
        end
      end

      context 'subsequent update with NO locations' do
        before do
          subject.work
          expect(created_client.locations.count).to eq(5)
          stub_request(:get, "#{client_uid}?access_token=#{token}").
              with(:headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).
              to_return(status: 200, body: fixture('client-g5-c-1soj8m6e-g5-multifamily-no-locations.json'), headers: {})
        end

        it 'removes orphaned locations' do
          expect { subject.work }.to change { created_client.locations.count }.from(5).to(0)
        end
      end
    end

    context 'with client and location uids' do
      subject { described_class.new(client_uid: client_uid, location_uid: location_uid) }
      before do
        allow(G5Updatable::Fetcher).to receive(:do_with_username_pw_access_token).and_yield(token)
        stub_request(:get, "#{location_uid}?access_token=#{token}").
            with(:headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).
            to_return(status: 200, body: fixture('location-g5-cl-1soj9pe2-541-apartments.json'), headers: {})
      end

      let(:created_location) { G5Updatable::Location.last }

      it 'creates a location' do
        expect { subject.work }.to change { G5Updatable::Location.count }.by(1)
        expect(created_location.urn).to eq('g5-cl-1soj9pe2-541-apartments')
      end
    end
  end
end