require 'rails_helper'

describe LHS::Record do
  context 'create' do
    let(:datastore) { 'http://local.ch/v2' }

    before(:each) do
      LHC.config.placeholder('datastore', datastore)
      class Feedback < LHS::Record
        endpoint ':datastore/content-ads/:campaign_id/feedbacks'
        endpoint ':datastore/feedbacks'
      end
    end

    let(:object) do
      {
        recommended: true,
        source_id: 'aaa'
      }
    end

    it 'creates new record on the backend' do
      stub_request(:post, "#{datastore}/feedbacks")
        .with(body: object.to_json)
        .to_return(status: 200, body: object.to_json)
      record = Feedback.create(object)
      expect(record).to be_kind_of Feedback
      expect(record.recommended).to eq true
      expect(record.errors).to eq nil
    end

    it 'uses proper endpoint when creating data' do
      stub_request(:post, "#{datastore}/content-ads/12345/feedbacks")
        .with(body: object.to_json)
        .to_return(status: 200, body: object.to_json)
      Feedback.create(object.merge(campaign_id: '12345'))
    end

    it 'merges backend response object with object' do
      body = object.merge(additional_key: 1)
      stub_request(:post, "#{datastore}/content-ads/12345/feedbacks")
        .with(body: object.to_json)
        .to_return(status: 200, body: body.to_json)
      data = Feedback.create(object.merge(campaign_id: '12345'))
      expect(data.additional_key).to eq 1
    end

    context 'creation errors' do
      let(:creation_error) do
        {
          "status" => 400,
          "fields" => [
            {
              "name" => "ratings",
              "details" => [{ "code" => "REQUIRED_PROPERTY_VALUE" }]
            }, {
              "name" => "recommended",
              "details" => [{ "code" => "REQUIRED_PROPERTY_VALUE" }]
            }
          ]
        }
      end

      it 'provides errors accessor on the record when creation failed using create' do
        stub_request(:post, "#{datastore}/content-ads/12345/feedbacks")
          .to_return(status: 400, body: creation_error.to_json)
        feedback = Feedback.create(object.merge(campaign_id: '12345'))
        expect(feedback.errors).to be_kind_of LHS::Errors
      end

      it 'raises an exception when creation failed using create!' do
        stub_request(:post, "#{datastore}/content-ads/12345/feedbacks")
          .to_return(status: 400, body: creation_error.to_json)
        expect(lambda {
          Feedback.create!(object.merge(campaign_id: '12345'))
        }).to raise_error(LHC::Error)
      end
    end

    context 'custom setters' do
      before(:each) do
        class Feedback
          def ratings=(ratings)
            _raw[:ratings] = ratings.map { |k, v| { name: k.to_s, value: v } }
          end
        end

        stub_request(:post, "#{datastore}/feedbacks")
          .with(body: { ratings: converted_ratings }.to_json)
          .to_return(status: 200, body: { ratings: converted_ratings }.to_json)
      end

      let(:ratings) do
        {
          a: 1,
          b: 2
        }
      end

      let(:converted_ratings) do
        [
          { name: 'a', value: 1 },
          { name: 'b', value: 2 }
        ]
      end

      it 'are used by create' do
        feedback = Feedback.create(ratings: ratings)
        expect(feedback.ratings.raw).to eq(converted_ratings)
      end

      it 'can be used directly to change raw data' do
        feedback = Feedback.create(ratings: ratings)
        feedback.ratings = { z: 3 }
        expect(feedback.ratings.first.name).to eq 'z'
      end

      context 'and custom getters' do
        before(:each) do
          class Feedback
            def ratings
              Hash[_raw[:ratings].map { |r| [r[:name].to_sym, r[:value]] }]
            end
          end
        end

        it 'uses custom getters to show data for exploration' do
          feedback = Feedback.create(ratings: ratings)
          expect(feedback.ratings).to eq(ratings)
        end
      end
    end
  end
end