# encoding: utf-8
require File.expand_path('../../../../../easy_extensions/test/spec/spec_helper', __FILE__)

describe EasyMeetingsController do

  render_views

  context 'with anonymous user' do
    describe 'GET new' do

      it "should not respond with ok" do
        get :new
        expect( response ).not_to have_http_status( 200 )
      end

    end

    describe "PUT update" do
      let!(:meeting) { FactoryGirl.create(:easy_meeting) }

      it "should not change anything" do
        meeting.reload
        expect {
          put :update, :id => meeting, :easy_meeting => { :name => 'New name', :start_time => Time.now }
          meeting.reload
        }.to_not change { meeting.attributes }
      end

    end
  end

  context 'with admin user', logged: :admin do
    let(:room) { FactoryGirl.create(:easy_room, capacity: 3) }

    describe 'GET new' do

      it "should return a new form" do
        get :new
        expect( response.body ).to have_css('form#new_easy_meeting')
      end

      it "should not render layout for xhr requests" do
        xhr :get, :new
        expect( response.body ).to have_css('form#new_easy_meeting')
        expect( response.body ).not_to have_css('div#content')
      end

      it "should fill attributes from params" do
        start_time = Time.now
        end_time = start_time + 2.hours
        get :new, :easy_meeting => { :name => 'Param name', :start_time => start_time, :end_time => end_time }

        expect( response.body ).to have_selector("input[name='easy_meeting[name]'][value='Param name']")
        expect( response.body ).to have_selector("input[name='easy_meeting[start_time][date]'][value='#{start_time.to_date.to_param}']")
        expect( response.body ).to have_selector("input[name='easy_meeting[start_time][time]'][value='#{start_time.strftime('%H:%M')}']")
        expect( response.body ).to have_selector("input[name='easy_meeting[end_time][date]'][value='#{end_time.to_date.to_param}']")
        expect( response.body ).to have_selector("input[name='easy_meeting[end_time][time]'][value='#{end_time.strftime('%H:%M')}']")
      end

    end

    describe 'POST create with json format' do
      it "creates a meeting if attributes are valid" do
        meeting_attrs = FactoryGirl.attributes_for(:easy_meeting)
        expect {post :create, :format => 'json', :easy_meeting => meeting_attrs}.to change(EasyMeeting, :count).by(1)
        meeting = EasyMeeting.last
        expect( meeting.author_id ).to eq( User.current.id )
        expect( meeting.name ).to eq( meeting_attrs[:name] )
        expect( meeting.description ).to eq( meeting_attrs[:description] )
        expect( meeting.start_time.utc.to_param ).to eq( meeting_attrs[:start_time].utc.to_param )
        expect( meeting.end_time.utc.to_param ).to eq( meeting_attrs[:end_time].utc.to_param )
      end

      it "renders validation errors if attributes are not valid" do
        meeting_attrs = FactoryGirl.attributes_for(:easy_meeting)
        meeting_attrs[:name] = ''
        expect {post :create, :format => 'json', :easy_meeting => meeting_attrs}.not_to change(EasyMeeting, :count)

        expect( response ).to have_http_status( 422 )
        expect( json[:errors][0] ).to include("Name cannot be blank")
      end

      it "does not allow to invite more users than the capacity of the meeting room" do
        meeting_attrs = FactoryGirl.attributes_for(:easy_meeting)
        meeting_attrs[:easy_room_id] = room.id
        meeting_attrs[:mails] = 'user1@example.com, user2@example.com, user3@example.com, user4@example.com'
        expect {post :create, :format => 'json', :easy_meeting => meeting_attrs}.not_to change(EasyMeeting, :count)
      end

      it "does not allow to create multiple meetings in the same room at the same time" do
        meeting_attrs = FactoryGirl.attributes_for(:easy_meeting)
        meeting_attrs[:easy_room_id] = room.id
        expect {post :create, :format => 'json', :easy_meeting => meeting_attrs}.to change(EasyMeeting, :count).by(1)
        expect( response ).to have_http_status( 200 )
        expect {post :create, :format => 'json', :easy_meeting => meeting_attrs}.not_to change(EasyMeeting, :count)
        expect( response ).to have_http_status( 422 )

        expect( json[:errors][0] ).to include("There is another meeting in the same room")
      end
    end

    describe 'PUT update with json format' do
      # only authors can update their meetings
      let(:meeting) { FactoryGirl.create(:easy_meeting, author: User.current) }

      it "updates attributes" do
        put :update, id: meeting, format: 'json', easy_meeting: {name: 'Updated name'}
        meeting.reload
        expect( meeting.name ).to eq( 'Updated name' )
      end

      it "renders validation errors" do
        put :update, :id => meeting.id, :format => 'json', :easy_meeting => {:name => ''}
        expect( response ).to have_http_status 422
        err = I18n.t(:field_name)
        err << ' ' << I18n.t(:'activerecord.errors.messages.blank')
        expect( json[:errors][0] ).to include(err)
      end
    end

    describe 'DELETE destroy with json format' do
      let!(:meeting) { FactoryGirl.create(:easy_meeting) }

      it "destroys meeting" do
        expect {delete :destroy, :id => meeting, :format => 'json'}.to change(EasyMeeting, :count).by(-1)
      end
    end

    describe 'User invitations' do
      let(:english_user) { FactoryGirl.create(:user, language: 'en') }
      let(:spanish_user) { FactoryGirl.create(:user, language: 'es') }
      let(:meeting) { FactoryGirl.create(:easy_meeting, mails: 'external1@example.com, external2@example.com', author: User.current) }
      let(:project) { FactoryGirl.create(:project) }

      before do
        ActionMailer::Base.deliveries = []
      end

      it "invites users and external users on creation" do
        meeting_attrs = FactoryGirl.attributes_for(:easy_meeting, {
          user_ids: [spanish_user.id, english_user.id],
          mails: 'external1@example.com, external2@example.com'
        })

        post :create, :format => 'json', :easy_meeting => meeting_attrs
        [
          spanish_user.mail,
          english_user.mail,
          'external1@example.com',
          'external2@example.com'
        ].each do |mail|
          msg = ActionMailer::Base.deliveries.detect {|msg| msg.bcc == [mail]}
          expect( msg ).not_to be_nil
          expect( msg.attachments.detect{|a| a.content_type =~ /application\/ical/} ).not_to be_nil
          expect( msg.html_part.body.to_s ).to include( meeting_attrs[:description] )
        end
      end

      it "invites added external users on update" do
        put :update, id: meeting, format: 'json', easy_meeting: {mails: "#{meeting.mails}, external3@example.com"}
        msg = ActionMailer::Base.deliveries.detect {|msg| msg.bcc == ['external3@example.com']}
        expect( msg ).not_to be_nil
      end

      it "invites users in their language" do
        meeting_attrs = FactoryGirl.attributes_for(:easy_meeting, user_ids: [spanish_user.id])
        post :create, format: 'json', easy_meeting: meeting_attrs
        expect( ActionMailer::Base.deliveries.last.subject ).to include('Invitación a una reunión')
      end

      it "has project name in notification email subject" do
        meeting_attrs = FactoryGirl.attributes_for(:easy_meeting, user_ids: [english_user.id], project_id: project.id)
        post :create, format: 'json', easy_meeting: meeting_attrs
        msg = ActionMailer::Base.deliveries.last
        expect( msg.subject ).to include(project.name)
      end

      it "has description in notification email body" do
        description = 'This is a meeting description.'
        meeting_attrs = FactoryGirl.attributes_for(:easy_meeting, user_ids: [english_user.id], mails: 'test@example.com', description: description)
        post :create, format: 'json', easy_meeting: meeting_attrs
        expect( ActionMailer::Base.deliveries.size ).to eq( 2 )
        ActionMailer::Base.deliveries.each do |msg|
          expect( msg.html_part.body.to_s ).to include(description)
        end
      end
    end

  end

end
