require 'spec_helper'

describe "MusicSessionScheduler" do

  before(:all) do
    MusicSession.delete_all
    @scheduler = MusicSessionScheduler.new
  end

  describe "session scheduling" do

    it "should reschedule sessions that meet criteria" do
      ms = FactoryGirl.create(:recurring_music_session_weekly)
      ms.next_session_scheduled.should == false

      MusicSession.all.count.should == 1

      @scheduler.run

      MusicSession.all.count.should == 1

      # move the session back more than 4 hours
      ms.scheduled_start = Time.now - 5.hours
      ms.save!

      # run the scheduler again
      @scheduler.run

      MusicSession.all.count.should == 2

      MusicSession.where(:next_session_scheduled => true).count.should == 1
    end

    it "should not reschedule session that does not meet criteria" do
      # test non-recurring session
      ms = FactoryGirl.create(:music_session)

      MusicSession.all.count.should == 1
      
      @scheduler.run
      MusicSession.all.count.should == 1

      ms.scheduled_start = Time.now - 3.hours
      ms.save!

      @scheduler.run
      MusicSession.all.count.should == 1

      # test canceled session
      ms = FactoryGirl.create(:recurring_music_session_weekly)
      MusicSession.all.count.should == 2

      ms.canceled = true
      ms.save!
      
      @scheduler.run
      MusicSession.all.count.should == 2

      # test already rescheduled
      ms = FactoryGirl.create(:recurring_music_session_weekly)
      ms.next_session_scheduled = true
      ms.save!

      MusicSession.all.count.should == 3

      @scheduler.run
      MusicSession.all.count.should == 3
    end

    it "should copy all fields" do
      SessionInfoComment.delete_all
      Notification.delete_all
      RsvpRequestRsvpSlot.delete_all
      RsvpRequest.delete_all
      RsvpSlot.delete_all
      Invitation.delete_all
      MusicSession.delete_all
      User.delete_all

      # set up data
      creator = FactoryGirl.create(:user)
      responder1 = FactoryGirl.create(:user)
      responder2 = FactoryGirl.create(:user)
      responder3 = FactoryGirl.create(:user)
      responder4 = FactoryGirl.create(:user)
      responder5 = FactoryGirl.create(:user)

      music_session = FactoryGirl.create(:music_session, :creator => creator)

      # do one more delete since the MusicSession factory creates a chosen RSVP slot
      RsvpRequestRsvpSlot.delete_all
      RsvpRequest.delete_all
      RsvpSlot.delete_all

      slot1 = FactoryGirl.create(:rsvp_slot, :music_session => music_session, :instrument => JamRuby::Instrument.find('electric guitar'))
      slot2 = FactoryGirl.create(:rsvp_slot, :music_session => music_session, :instrument => JamRuby::Instrument.find('drums'))
      slot3 = FactoryGirl.create(:rsvp_slot, :music_session => music_session, :instrument => JamRuby::Instrument.find('bass guitar'))
      slot4 = FactoryGirl.create(:rsvp_slot, :music_session => music_session, :instrument => JamRuby::Instrument.find('computer'))

      # create RSVPs
      rsvp1 = RsvpRequest.create({:session_id => music_session.id, :rsvp_slots => [slot1.id, slot2.id]}, responder1)
      rsvp2 = RsvpRequest.create({:session_id => music_session.id, :rsvp_slots => [slot2.id]}, responder2)
      rsvp3 = RsvpRequest.create({:session_id => music_session.id, :rsvp_slots => [slot3.id]}, responder3)
      rsvp4 = RsvpRequest.create({:session_id => music_session.id, :rsvp_slots => [slot4.id]}, responder4)
      rsvp5 = RsvpRequest.create({:session_id => music_session.id, :rsvp_slots => [slot4.id]}, responder5)

      # approve RSVPs
      rs1 = RsvpRequestRsvpSlot.find_by_rsvp_request_id_and_rsvp_slot_id(rsvp1.id, slot1.id)

      rs2 = RsvpRequestRsvpSlot.find_by_rsvp_request_id_and_rsvp_slot_id(rsvp1.id, slot2.id)
      RsvpRequest.update({:id => rsvp1.id, :session_id => music_session.id, :rsvp_responses => [{:request_slot_id => rs1.id, :accept => true}, {:request_slot_id => rs2.id, :accept => false}]}, creator)

      rs2 = RsvpRequestRsvpSlot.find_by_rsvp_request_id_and_rsvp_slot_id(rsvp2.id, slot2.id)
      RsvpRequest.update({:id => rsvp1.id, :session_id => music_session.id, :rsvp_responses => [{:request_slot_id => rs2.id, :accept => true}]}, creator)

      rs3 = RsvpRequestRsvpSlot.find_by_rsvp_request_id_and_rsvp_slot_id(rsvp3.id, slot3.id)
      RsvpRequest.update({:id => rsvp3.id, :session_id => music_session.id, :rsvp_responses => [{:request_slot_id => rs3.id, :accept => true}]}, creator)

      # cancel RSVP for all future sessions
      RsvpRequest.cancel({:id => rsvp3.id, :session_id => music_session.id, :cancelled => "all"}, creator)

      # cancel slot 4 for responder 4
      rs4 = RsvpRequestRsvpSlot.find_by_rsvp_request_id_and_rsvp_slot_id(rsvp4.id, slot4.id)
      RsvpRequest.cancel({:id => rsvp4.id, :session_id => music_session.id, :cancelled => "yes"}, responder4)

      # cancel slot 4 for responder 5
      rs5 = RsvpRequestRsvpSlot.find_by_rsvp_request_id_and_rsvp_slot_id(rsvp5.id, slot4.id)
      RsvpRequest.cancel({:id => rsvp5.id, :session_id => music_session.id, :cancelled => "yes"}, responder5)

      # copy the session and its details
      new_session = music_session.copy

      # verify session fields
      new_session.description.should == music_session.description
      new_session.user_id.should == music_session.user_id
      new_session.band_id.should == music_session.band_id
      new_session.fan_access.should == music_session.fan_access
      new_session.scheduled_start.should == music_session.scheduled_start + 1.week
      new_session.scheduled_duration.should == music_session.scheduled_duration
      new_session.musician_access.should == music_session.musician_access
      new_session.approval_required.should == music_session.approval_required
      new_session.fan_chat.should == music_session.fan_chat
      new_session.genre_id.should == music_session.genre_id
      new_session.legal_policy.should == music_session.legal_policy
      new_session.language.should == music_session.language
      new_session.name.should == music_session.name
      new_session.recurring_mode.should == music_session.recurring_mode
      new_session.timezone.should == music_session.timezone
      new_session.open_rsvps.should == music_session.open_rsvps
      new_session.is_unstructured_rsvp.should == music_session.is_unstructured_rsvp
      new_session.legal_terms.should == music_session.legal_terms

      # verify rsvp details (slots, rsvp requests, etc.)
      new_session.rsvp_slots.count.should == music_session.rsvp_slots.count
      s1 = RsvpSlot.where(:instrument_id => 'electric guitar').order("created_at ASC").last
      s2 = RsvpSlot.where(:instrument_id => 'drums').order("created_at ASC").last
      s3 = RsvpSlot.where(:instrument_id => 'bass guitar').order("created_at ASC").last
      s4 = RsvpSlot.where(:instrument_id => 'computer').order("created_at ASC").last

      r1 = RsvpRequest.where(:user_id => responder1.id).order("created_at ASC").last
      r2 = RsvpRequest.where(:user_id => responder2.id).order("created_at ASC").last
      r3 = RsvpRequest.where(:user_id => responder3.id).order("created_at ASC").last
      r4 = RsvpRequest.where(:user_id => responder4.id).order("created_at ASC").last
      r5 = RsvpRequest.where(:user_id => responder5.id).order("created_at ASC").last

      # user 1
      RsvpRequestRsvpSlot.where(:rsvp_request_id => r1.id, :rsvp_slot_id => s1.id).count.should == 1 # approved
      RsvpRequestRsvpSlot.where(:rsvp_request_id => r1.id, :rsvp_slot_id => s2.id).count.should == 0 # declined

      # user 2
      RsvpRequestRsvpSlot.where(:rsvp_request_id => r2.id, :rsvp_slot_id => s2.id).count.should == 1 # approved

      # user 3
      RsvpRequestRsvpSlot.where(:rsvp_request_id => r3.id, :rsvp_slot_id => s3.id).count.should == 0 # cancelled all future

      # user 4
      RsvpRequestRsvpSlot.where(:rsvp_request_id => r4.id, :rsvp_slot_id => s4.id).count.should == 1 # 1-time cancellation

      # user 5
      RsvpRequestRsvpSlot.where(:rsvp_request_id => r5.id, :rsvp_slot_id => s4.id).count.should == 1 # 1-time cancellation

      # should copy all requests except the one that cancelled for all future sessions (3 original requests + 2 copied)
      RsvpRequest.all.count.should == 9
    end
  end
end