require 'spec_helper'

describe Harmony::Service::RpcService do
  
  describe "#work_with_params" do
    let(:metadata) { instance_double("Metadata", reply_to: "harmony.trello", correlation_id: "abc123") }
    let(:handler) { handler = double("Object") }
      
    context "ack!" do
      before(:each) do
        allow(handler).to receive(:work_with_request).with(kind_of(request.class)) { response }
        allow(subject).to receive(:new_handler) { handler }
        allow(subject).to receive(:send_response_json)
        allow(subject).to receive(:ack!) 
        allow(subject).to receive(:reject!)         
        subject.work_with_params(Oj.dump(request), {}, metadata)
      end    
      
      context "calculation" do
        let(:request) { Harmony::Service::Calculator::Request.new(harmony_user_email: "matt@futureworkshops.com", inputs: {"lat" => "51.0", "lon" => "0.1"}) }
        let(:response) { Harmony::Service::Calculator::Response.new(outputs: {price: 50})}
      
        it { expect(subject).to have_received(:send_response_json).with("{\"^o\":\"Harmony::Service::Calculator::Response\",\"outputs\":{\":price\":50}}", "harmony.trello", "abc123", any_args) }
        it { expect(subject).to have_received(:ack!) }
      end
      
      context "action list" do
        context "list" do
          let(:request) { Harmony::Service::ActionList::ListRequest.new(harmony_user_email: "matt@futureworkshops.com", page: 0, per_page: 10) }
          let(:response) { [{id: 1, title: "Carrots"}]}
      
          it { expect(subject).to have_received(:send_response_json).with("[{\":id\":1,\":title\":\"Carrots\"}]", "harmony.trello", "abc123") }
          it { expect(subject).to have_received(:ack!) }
        end
        
        context "item" do
          let(:request) { Harmony::Service::ActionList::ItemRequest.new(harmony_user_email: "matt@futureworkshops.com", id: 1) }
          let(:response) { {id: 1, title: "Carrots", subtitle: "Bag of Carrots", detail_html: "<html><body>Carrots</body></html>"} }
      
            it { expect(subject).to have_received(:send_response_json).with("{\":id\":1,\":title\":\"Carrots\",\":subtitle\":\"Bag of Carrots\",\":detail_html\":\"<html><body>Carrots</body></html>\"}", "harmony.trello", "abc123") }
          it { expect(subject).to have_received(:ack!) }
        end
        
        context "action" do
          let(:request) { Harmony::Service::ActionList::ActionRequest.new(harmony_user_email: "matt@futureworkshops.com", id: 1, action: "Done") }
          let(:response) { Harmony::Service::Response.new }
      
          it { expect(subject).to have_received(:send_response_json).with("{\"^o\":\"Harmony::Service::Response\"}", "harmony.trello", "abc123") }
          it { expect(subject).to have_received(:ack!) }
        end
      end
      
      context "chart" do
        let(:request) { Harmony::Service::Chart::Request.new(harmony_user_email: "matt@futureworkshops.com") }
        let(:response) { Harmony::Service::Chart::Response.new(x_values: ["Jan", "Feb", "Mar"], y_values: [10, 20, 40])}
        it { expect(subject).to have_received(:send_response_json).with("{\"^o\":\"Harmony::Service::Chart::Response\",\"x_values\":[\"Jan\",\"Feb\",\"Mar\"],\"y_values\":[10,20,40]}", "harmony.trello", "abc123") }
        it { expect(subject).to have_received(:ack!) }
      end
      
      context "form" do
        context 'get' do
          let(:request) { Harmony::Service::Form::GetRequest.new(harmony_user_email: "matt@futureworkshops.com", inputs: ['satisfaction_level']) }
          let(:response) { Harmony::Service::Form::GetResponse.new({input_values: [{'satisfaction_level': ['1','2','3']}]})}
          it { expect(subject).to have_received(:send_response_json).with("{\"^o\":\"Harmony::Service::Form::GetResponse\",\"input_values\":[{\":satisfaction_level\":[\"1\",\"2\",\"3\"]}],\"options\":{}}", "harmony.trello", "abc123") }
          it { expect(subject).to have_received(:ack!) }
        end
      end
      
      context "flow ended" do
        let(:request) { Harmony::Service::Flow::EndedRequest.new(harmony_user_email: "matt@futureworkshops.com", pages: [{page_id: 1}]) }
        let(:response) { Harmony::Service::Response.new }
        it { expect(subject).to have_received(:send_response_json).with("{\"^o\":\"Harmony::Service::Response\"}", "harmony.trello", "abc123") }
        it { expect(subject).to have_received(:ack!) }
      end
      
      context "app notification" do
        let(:request) { Harmony::Service::Notification::Request.new }
        let(:response) { Harmony::Service::Notification::AppResponse.new(text: 'Check out the new data')}
        it { expect(subject).to have_received(:send_response_json).with("{\"^o\":\"Harmony::Service::Notification::AppResponse\",\"text\":\"Check out the new data\"}", "harmony.trello", "abc123") }
        it { expect(subject).to have_received(:ack!) }
      end
      
      context "attribute names" do
        let(:request) { Harmony::Service::AttributeNamesRequest.new }
        let(:response) { Harmony::Service::AttributeNamesResponse.new}
        it { expect(subject).to have_received(:send_response_json).with("{\"^o\":\"Harmony::Service::AttributeNamesResponse\",\"options\":{}}", "harmony.trello", "abc123") }
        it { expect(subject).to have_received(:ack!) }
      end

      context "oauth_token" do
        let(:request) { Harmony::Service::OauthTokenRequest.new }
        let(:response) { Harmony::Service::OauthTokenResponse.new}
        it { expect(subject).to have_received(:send_response_json).with("{\"^o\":\"Harmony::Service::OauthTokenResponse\"}", "harmony.trello", "abc123") }
        it { expect(subject).to have_received(:ack!) }
      end
      
      context "exception" do
        let(:handler) do 
          handler = double("Object")
          expect(handler).to receive(:work_with_request).and_raise("Could not complete.")
          handler
        end
        
        let(:request) { Harmony::Service::Notification::Request.new }
        
        it { expect(subject).to have_received(:send_response_json).with(/Could not complete/,"harmony.trello", "abc123") }
        it { expect(subject).to have_received(:reject!) }
      end
      
    end    
  
    context "unacceptable request class" do
      before(:each) do
        allow(subject).to receive(:work_with_request).and_raise("A timeout occured")
        allow(subject).to receive(:send_response_json)
        allow(subject).to receive(:reject!)
            
        metadata = instance_double("Metadata", reply_to: "harmony.trello", correlation_id: "abc123")
        subject.work_with_params("{\"trello_board_id\": \"12345\"}", {}, metadata)
      end
    
      it { expect(subject).to have_received(:send_response_json).with(/Unacceptable request class: Hash/,"harmony.trello", "abc123") }
      it { expect(subject).to have_received(:reject!) }
    end
  end
  

end