require 'rails_helper'
require 'date'

RSpec.describe UserRewards::HypeTrain do
  include ServiceHelper
  include Code::Justin::Tv::Commerce::Percy

  describe "#grant_rewards" do
    describe "when hype train is found and rewards are granted" do
      let(:success_response) do
        data = Code::Justin::Tv::Commerce::Percy::AdminGrantHypeTrainRewardsResp.new
        data.hype_train = Code::Justin::Tv::Commerce::Percy::HypeTrain.new
        data.granted_rewards << Code::Justin::Tv::Commerce::Percy::Reward.new(id: "12345", type: "EMOTE")
        data.user_owned_rewards << Code::Justin::Tv::Commerce::Percy::Reward.new(id: "12345", type: "EMOTE")
        data.user_owned_rewards << Code::Justin::Tv::Commerce::Percy::Reward.new(id: "67890", type: "EMOTE")

        config = Code::Justin::Tv::Commerce::Percy::HypeTrainConfig.new
        level_settings = (1...5).map do |i|
          setting = Code::Justin::Tv::Commerce::Percy::LevelSetting.new
          setting.rewards << Code::Justin::Tv::Commerce::Percy::Reward.new(id: i.to_s, type: "EMOTE")
          setting.level = i
          setting
        end
        config.difficulty = "EASY"
        config.difficulty_settings << Code::Justin::Tv::Commerce::Percy::DifficultySetting.new(difficulty: "EASY", level_settings: level_settings)
        data.hype_train.config = config

        data.participation_totals << Code::Justin::Tv::Commerce::Percy::Participation.new(source: "BITS", action: "CHEER", quantity: 100)

        Twirp::ClientResp.new(data, nil)
      end

      it "returns found hype train and rewards" do
        expect(described_class.twirp_client).to(receive(:admin_grant_hype_train_rewards)).and_return(success_response)
        hype_train, rewards, user_owned_rewards, participation_totals = described_class.grant_rewards("123", "456", Time.now)
        expect(hype_train).to be_present
        expect(rewards).not_to be_empty
        expect(user_owned_rewards).not_to be_empty
        expect(participation_totals).not_to be_empty
      end
    end

    describe "when no hype train is found" do
      let(:empty_response) do
        data = Code::Justin::Tv::Commerce::Percy::AdminGrantHypeTrainRewardsResp.new
        Twirp::ClientResp.new(data, nil)
      end

      it "returns nil and empty if hype train and rewards are not found" do
        expect(described_class.twirp_client).to(receive(:admin_grant_hype_train_rewards)).and_return(empty_response)
        hype_train, rewards = described_class.grant_rewards("123", "456", Time.now)
        expect(hype_train).not_to be_present
        expect(rewards).to be_empty
      end
    end

    describe "service call errors" do
      let(:error_response) do
        Twirp::ClientResp.new(nil, Twirp::Error.new(:internal, "some error", {}))
      end

      it "throws an exception if service call fails" do
        expect(described_class.twirp_client).to(receive(:admin_grant_hype_train_rewards)).and_return(error_response)
        expect do
          described_class.grant_rewards("123", "456", Time.now)
        end.to raise_error "some error"
      end
    end
  end
end