require 'rails_helper'
require 'ostruct'

class Helper
  include UserRewards::HypeTrainHelper
end

RSpec.describe UserRewards::HypeTrainHelper do
  let(:helper) { Helper.new }

  let(:hype_train) do
    to_recursive_ostruct({
                           config: {
                             difficulty: :EASY,
                             difficulty_settings: [
                               {
                                 difficulty: :EASY,
                                 level_settings: [
                                   {
                                     level: 4,
                                     goal: 60,
                                     rewards: [
                                       {
                                         id: "41",
                                         type: :EMOTE
                                       },
                                       {
                                         id: "42",
                                         type: :Emote
                                       }
                                     ]
                                   }
                                 ]
                               }
                             ]
                           },
                           level_progress: {
                             setting: {
                               level: 5,
                               rewards: [
                                 {
                                   id: "12345",
                                   type: :EMOTE
                                 },
                                 {
                                   id: "current_conductor",
                                   type: :BADGE
                                 }
                               ]
                             },
                             progression: 80,
                             goal: 100
                           },
                           started_at: Time.now,
                           ended_at: Time.now
                         })
  end

  describe "completed_level" do
    it "returns the completed level for the given hype train" do
      expect(helper.completed_level(hype_train)).to eq(4)
    end
  end

  describe "#current_level" do
    it "returns the current level for the given hype train" do
      expect(helper.current_level(hype_train)).to eq(5)
    end
  end

  describe "#badge_image_url" do
    it "returns the former conductor image URL by default" do
      expect(helper.badge_image_url("123")).to_not be_empty
    end
  end

  describe "#emote_image_url" do
    it "returns the emote image url at 5.0" do
      expect(helper.emote_image_url("12345")).to eq("https://static-cdn.jtvnw.net/emoticons/v1/12345/5.0")
    end
  end

  describe "#filter_rewards_by_type" do
    it "filters rewards based on type" do
      expect(helper.filter_rewards_by_type(hype_train.level_progress.setting.rewards, :EMOTE).size).to eq(1)
      expect(helper.filter_rewards_by_type(hype_train.level_progress.setting.rewards, :BADGE).size).to eq(1)
      expect(helper.filter_rewards_by_type(hype_train.level_progress.setting.rewards, :OTHER).size).to eq(0)
    end
  end

  describe "#all_eligible_rewards_by_level" do
    it "returns all rewards eligible given the hype train level" do
      rewards = helper.all_eligible_rewards_by_level(hype_train, [])
      expect(rewards.size).to eq(1)
      expect(rewards.first.size).to eq(2)
    end

    it "marks the rewards that the user already has" do
      rewards = helper.all_eligible_rewards_by_level(hype_train, [OpenStruct.new({id: "42", type: :EMOTE})])
      expect(rewards.size).to eq(1)
      expect(rewards.first.size).to eq(2)
      expect(rewards.first.second.owned).to be_truthy
    end
  end
end

def to_recursive_ostruct(hash)
  OpenStruct.new(hash.each_with_object({}) do |(key, val), memo|
    memo[key] = if val.is_a?(Hash)
                  to_recursive_ostruct(val)
                elsif val.is_a?(Array)
                  val.map { |v| to_recursive_ostruct(v) }
                else
                  val
                end
  end)
end