# this test used maxmind data in scores_create_tables.sql to succeed.  We lost that seed data when we retired
# the jam-cloud/db/ project. We could bring it back of course
=begin
require 'spec_helper'
require 'time_difference'


describe 'Musician Search Model' do

  let!(:searcher) { FactoryGirl.create(:austin_user) }
  let!(:search) { MusicianSearch.create_search(searcher) }

  let!(:austin_user) { FactoryGirl.create(:austin_user) }
  let!(:dallas_user) { FactoryGirl.create(:dallas_user) }
  let!(:miami_user) { FactoryGirl.create(:miami_user) }
  let!(:seattle_user) { FactoryGirl.create(:seattle_user) }

  let!(:user_types) { [:austin_user, :dallas_user, :miami_user, :seattle_user] }

  describe "creates search obj" do
    before(:all) do
      User.delete_all
      Score.connection.execute('delete from current_network_scores').check
      Score.connection.execute('delete from scores').check
    end
    
    it "associates to user" do
      expect(search.user).to eq(searcher)
      searcher.reload
      expect(searcher.musician_search).to eq(search)
    end

    it "sets json" do
      search.update_json_value(MusicianSearch::KEY_GIGS, MusicianSearch::GIG_COUNTS[1])
      expect(search.json[MusicianSearch::KEY_GIGS]).to eq(MusicianSearch::GIG_COUNTS[1])
    end
  end

  describe "filtering criteria" do
    before(:all) do
      User.delete_all
    end
    # it "filters musicians" do
    #   expect(search.do_search(per_page: User.musicians.count).count).to eq(User.musicians.count)
    # end

    describe "filters by age" do 
      before(:all) do        
        @users = []
        today = Date.today
        MusicianSearch::AGE_COUNTS.each_with_index do |age, idx|
          dd = today - age.years - 1.day
          @users << FactoryGirl.create(:austin_user, :birth_date => dd)
          @users << FactoryGirl.create(:dallas_user, :birth_date => dd)
          @users << FactoryGirl.create(:miami_user, :birth_date => dd)
          @users << FactoryGirl.create(:seattle_user, :birth_date => dd)
        end
      end

      it "filters by one age" do
        age = MusicianSearch::AGE_COUNTS[0]
        search.update_json_value(MusicianSearch::KEY_AGES, [age])
        today = Date.today.to_time
        search.do_search.all.each do |uu|
          diff = TimeDifference.between(uu.birth_date.to_time, today).in_years
          expect(diff).to be >= age
          expect(diff).to be < MusicianSearch::AGE_COUNTS[1]
        end
      end

      it "filters by multiple ages" do
        ages = MusicianSearch::AGE_COUNTS[0..2]
        search.update_json_value(MusicianSearch::KEY_AGES, ages[0..1])
        today = Date.today.to_time
        search.do_search.all.each do |uu|
          diff = TimeDifference.between(uu.birth_date.to_time, today).in_years
          expect(diff).to be >= ages.first
          expect(diff).to be < ages.last
        end
      end

      it "skips filtering by ages" do
        search.update_json_value(MusicianSearch::KEY_AGES, [MusicianSearch::ANY_VAL_INT])
        search.do_search.to_sql =~ /(birth_date)/
        expect($1).to eq(nil)
      end
    end

    describe "filtering by gig" do
      before(:all) do        
        user_types.each do |utype|
          FactoryGirl.create(utype, :concert_count => MusicianSearch::GIG_COUNTS[1])
        end
      end

      it "ignores gig count if any selected" do 
        search.update_json_value(MusicianSearch::KEY_GIGS, MusicianSearch::GIG_COUNTS[0])
        expect(search.do_search.count).to eq(User.musicians.count - 1)  # searcher is musician
      end

      it "filters by gig count" do
        search.update_json_value(MusicianSearch::KEY_GIGS, MusicianSearch::GIG_COUNTS[1])
        expect(search.do_search.count).to eq(user_types.count)
      end
    end

    describe "filtering by studio" do
      before(:all) do        
        user_types.each do |utype|
          FactoryGirl.create(utype, :studio_session_count => MusicianSearch::STUDIO_COUNTS[1])
        end
      end

      it "ignores studio count if any selected" do 
        search.update_json_value(MusicianSearch::KEY_STUDIOS, MusicianSearch::STUDIO_COUNTS[0])
        expect(search.do_search.count).to eq(User.musicians.count - 1)
      end

      it "filters by studio count" do
        search.update_json_value(MusicianSearch::KEY_STUDIOS, MusicianSearch::STUDIO_COUNTS[1])
        expect(search.do_search.count).to eq(user_types.count)
      end
    end

    describe "filters skills" do
      before(:all) do        
        MusicianSearch::SKILL_VALS.each do |val|
          user_types.each { |utype| FactoryGirl.create(utype, :skill_level => val) }
        end
      end

      it "get expected number per skill" do
        search.update_json_value(MusicianSearch::KEY_SKILL, MusicianSearch::SKILL_VALS[1])
        expect(search.do_search.count).to eq(user_types.count)
      end
    end

    describe "filters interests" do
      before(:all) do        
        
      end

      it "get expected number per interest" do
        MusicianSearch::INTEREST_VALS[1..-1].each do |val|
          user_types.each { |utype| FactoryGirl.create(utype, val => true, :paid_sessions_hourly_rate=>2300, :paid_sessions_daily_rate=>15000) }
        end
        search.update_json_value(MusicianSearch::KEY_INTERESTS, MusicianSearch::INTEREST_VALS[1])
        expect(search.do_search.count).to eq(user_types.count)
      end
    end

    describe "filters genres" do
      before(:all) do        
        user_types.each do |utype| 
          uu = FactoryGirl.create(utype)
          uu.update_genres([Genre.first.id, Genre.last.id], GenrePlayer::PROFILE)
        end
      end

      it "gets expected number of users" do
        search.update_json_value(MusicianSearch::KEY_GENRES, [Genre.first.id, Genre.last.id])
        expect(search.do_search.count).to eq(user_types.count)
      end
    end

    describe "filters instruments" do
      before(:all) do
        instruments = Instrument.first(user_types.count).collect do |inst|
          { instrument_id: inst.id, proficiency_level: 2, priority: 1 }
        end
        user_types[0..2].each do |utype| 
          uu = FactoryGirl.create(utype)
          uu.update_instruments(instruments)
        end
      end

      it "gets expected number of users" do
        instjson = [{ instrument_id: Instrument.first.id, proficiency_level: 2 },
                    { instrument_id: Instrument.first(2)[1].id, proficiency_level: 2 },
                    { instrument_id: 'foo', proficiency_level: 2 },
                   ]
        search.update_json_value(MusicianSearch::KEY_INSTRUMENTS, instjson)
        expect(search.do_search.count).to eq(3)
      end
    end
  end
  
  describe "sort order by distance" do
    before(:all) do
      User.delete_all
    end

    before(:each) do      
      create_phony_database
    end

    it "sorts by distance" do 
      musician_search = MusicianSearch.create_search(searcher)
      musician_search.update_json_value(MusicianSearch::KEY_SORT_ORDER, MusicianSearch::SORT_VALS[1])
      results = musician_search.do_search
      expect(results[0].id).to eq(austin_user.id)
      expect(results[1].id).to eq(dallas_user.id)
      expect(results[2].id).to eq(miami_user.id)
      expect(results[3].id).to eq(seattle_user.id)
    end
  end

  describe "sort order by latency" do
    before(:each) do
      User.delete_all
      Score.delete_all
      t = Time.now - 10.minute

      @user1 = FactoryGirl.create(:user, created_at: t+1.minute, last_jam_locidispid: 1)
      @user2 = FactoryGirl.create(:user, created_at: t+2.minute, last_jam_locidispid: 2)
      @user3 = FactoryGirl.create(:user, created_at: t+3.minute, last_jam_locidispid: 3)
      @user4 = FactoryGirl.create(:user, created_at: t+4.minute, last_jam_locidispid: 4)
      @user5 = FactoryGirl.create(:user, created_at: t+5.minute, last_jam_locidispid: 5)
      @user6 = FactoryGirl.create(:user, created_at: t+6.minute) # not geocoded
      @user7 = FactoryGirl.create(:user, created_at: t+7.minute, musician: false) # not musician

      @musicians = []
      @musicians << @user1
      @musicians << @user2
      @musicians << @user3
      @musicians << @user4
      @musicians << @user5
      @musicians << @user6

      # from these scores:
      #   user1 has scores other users in user1 location, and with user2, user3, user4
      #   user2 has scores with users in user3 and user4 location
      # Score.delete_all
      # Score.connection.execute('delete from current_network_scores').check
      Score.createx(1, 'a', 1, 1, 'a', 1, 10)
      Score.createx(1, 'a', 1, 2, 'b', 2, 20)
      Score.createx(1, 'a', 1, 3, 'c', 3, 30)
      Score.createx(1, 'a', 1, 4, 'd', 4, 40)
      Score.createx(2, 'b', 2, 3, 'c', 3, 15)
      Score.createx(2, 'b', 2, 4, 'd', 4, 70)
    end

    it "sorts by latency", intermittent: true do
      pending
      search.update_json_value(MusicianSearch::KEY_SORT_ORDER, MusicianSearch::SORT_VALS[0])
      results = search.do_search
      expect(results[0].id).to eq(@user1.id) # HAS FAILED HERE TOO
      expect(results[1].id).to eq(@user2.id)
      expect(results[2].id).to eq(@user3.id) # HAS FAILED INTERMITTENTLY
      expect(results[3].id).to eq(@user4.id)
    end

  end
  
  describe "produces accurate query description" do
    before(:all) do
      User.delete_all
    end
    
    it 'has default description' do
      expect(search.description).to match(/^Click search button to look for musicians/)
    end

    it 'has correct sort order description' do
      search.update_json_value(MusicianSearch::KEY_SORT_ORDER, MusicianSearch::SORT_VALS[1])
      str = MusicianSearch::SORT_ORDERS[search.json_value(MusicianSearch::KEY_SORT_ORDER)]
      expect(search.description).to match(/^Current Search: Sort = #{str}$/)
    end

    it 'has correct description for single-valued selections' do
      selections = [{
                      key: MusicianSearch::KEY_INTERESTS, 
                      value: MusicianSearch::INTEREST_VALS[1],
                      lookup: MusicianSearch::INTERESTS,
                      description: 'Interest'
                    },
                    {
                      key: MusicianSearch::KEY_SKILL, 
                      value: MusicianSearch::SKILL_VALS[1],
                      lookup: MusicianSearch::SKILL_LEVELS,
                      description: 'Skill'
                    },
                    {
                      key: MusicianSearch::KEY_STUDIOS, 
                      value: MusicianSearch::STUDIO_COUNTS[1],
                      lookup: MusicianSearch::STUDIOS_LABELS,
                      description: 'Studio Sessions'
                    },
                    {
                      key: MusicianSearch::KEY_GIGS, 
                      value: MusicianSearch::GIG_COUNTS[1],
                      lookup: MusicianSearch::GIG_LABELS,
                      description: 'Concert Gigs'
                    }]
      selections.each do |hash|
        search.update_json_value(hash[:key], hash[:value])
        json_val = search.json_value(hash[:key])
        expect(search.description).to match(/ #{hash[:description]} = #{hash[:lookup][json_val]}/)
      end
    end

    it 'has correct description for genres' do
      search.update_json_value(MusicianSearch::KEY_GENRES, [Genre.first.id, Genre.last.id])
      expect(search.description).to match(/ Genres = #{Genre.first.description}, #{Genre.last.description}/)
    end

    it 'has correct description for ages' do
      search.update_json_value(MusicianSearch::KEY_AGES, [MusicianSearch::AGE_COUNTS[0],MusicianSearch::AGE_COUNTS[1]])
      expect(search.description).to match(/ Ages = #{MusicianSearch::AGES[MusicianSearch::AGE_COUNTS[0]]}, #{MusicianSearch::AGES[MusicianSearch::AGE_COUNTS[1]]}/)
    end

    it 'has correct description for instruments' do
      instrs = Instrument.limit(2).order(:description)
      instjson = [{ id: instrs[0].id, level: 2 },
                  { id: instrs[1].id, level: 1 }
                 ]
      search.update_json_value(MusicianSearch::KEY_INSTRUMENTS, instjson)
      instr_descrip = "#{instrs[0].description} / #{MusicianSearch::INSTRUMENT_PROFICIENCY[2]}, #{instrs[1].description} / #{MusicianSearch::INSTRUMENT_PROFICIENCY[1]}"
      expect(search.description).to match(/ Instruments = #{Regexp.escape(instr_descrip)}/)
    end
    
  end
end
=end
