#  Copyright (c) 2012-2018, Schweizer Blasmusikverband. This file is part of
#  hitobito_sbv and licensed under the Affero General Public License version 3
#  or later. See the COPYING file at the top-level directory or at
#  https://github.com/hitobito/hitobito.

require 'spec_helper'

describe TagListsController do

  before { sign_in(people(:top_leader)) }

  let(:tag_list_double) { instance_double('tag_list') }
  let(:group) { groups(:top_group) }
  let(:leader) { people(:top_leader) }
  let(:bottom_member) { people(:bottom_member) }
  let(:root) { people(:root) }

  context 'authorization' do

    before do
      sign_in(people(:bottom_member))
      allow(tag_list_double).to receive(:add).and_return 0
      allow(tag_list_double).to receive(:remove).and_return 0
    end

    it 'filters out people whose tags we cannot manage from create request' do
      allow_any_instance_of(TagList).to receive(:new) do |people, _|
        expect(people).to contain_exactly bottom_member
        tag_list_double
      end
      post :create, params: { group_id: group.id, ids: [leader.id, bottom_member.id].join(','), tags: 'Tagname' }
    end

    it 'filters out people whose tags we cannot manage from destroy request' do
      allow_any_instance_of(TagList).to receive(:new) do |people, _|
        expect(people).to contain_exactly bottom_member
        tag_list_double
      end
      post :destroy, params: { group_id: group.id, ids: [leader.id, bottom_member.id].join(','), tags: 'Tagname' }
    end
  end

  context 'GET modal for bulk creating tags' do
    it 'shows modal' do
      get :new, xhr: true, params: { group_id: group.id, ids: [leader.id, bottom_member.id].join(',') }, format: :js
      expect(response).to have_http_status(:ok)
      expect(response).to render_template('tag_lists/new')
      expect(assigns(:manageable_people)).to contain_exactly leader, bottom_member
    end
  end

  context 'POST create' do
    before { allow(controller).to receive(:tag_list).and_return tag_list_double }

    it 'creates a tag and displays flash message' do
      expect(tag_list_double).to receive(:add).and_return(1)
      post :create, params: { group_id: group.id, ids: leader.id, tags: 'new tag' }
      expect(flash[:notice]).to include 'Ein Tag wurde erstellt'
    end

    it 'creates zero tags and displays flash message' do
      expect(tag_list_double).to receive(:add).and_return(0)
      post :create, params: { group_id: group.id, ids: leader.id, tags: 'new tag' }
      expect(flash[:notice]).to include 'Es wurden keine Tags erstellt'
    end

    it 'creates many tags and displays flash message' do
      expect(tag_list_double).to receive(:add).and_return(17)
      post :create, params: { group_id: group.id, ids: leader.id, tags: 'new tag' }
      expect(flash[:notice]).to include '17 Tags wurden erstellt'
    end
  end

  context 'GET modal for bulk deleting tags' do
    it 'shows modal' do
      get :deletable, xhr: true, params: { group_id: group.id, ids: [leader.id, bottom_member.id].join(',') }, format: :js
      expect(response).to have_http_status(:ok)
      expect(response).to render_template('tag_lists/deletable')
      expect(assigns(:manageable_people)).to contain_exactly leader, bottom_member
      expect(assigns(:existing_tags)).to be_empty
    end

    it 'shows modal with tags and correct count' do
      sign_in(root)
      tag_test  = ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('test')
      tag_once  = ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('once')
      tag_twice = ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('twice')
      leader.tag_list.add(tag_test, tag_once, tag_twice)
      leader.save!
      root.tag_list.add(tag_twice)
      root.save!
      bottom_member.tag_list.add(tag_once, 'another')
      bottom_member.save!
      get :deletable, xhr: true, params: { group_id: group.id, ids: [leader.id, root.id].join(',') },
                            format: :js
      expect(response).to have_http_status(:ok)
      expect(response).to render_template('tag_lists/deletable')
      expect(assigns(:manageable_people)).to contain_exactly leader, root
      expect(assigns(:existing_tags)).to contain_exactly([tag_test, 1],
                                                         [tag_once, 1],
                                                         [tag_twice, 2])
    end
  end

  context 'DELETE destroy' do
    before { allow(controller).to receive(:tag_list).and_return tag_list_double }

    it 'removes a tag and displays flash message' do
      expect(tag_list_double).to receive(:remove).and_return(1)
      post :destroy, params: { group_id: group.id, ids: leader.id, tags: 'existing' }
      expect(flash[:notice]).to include 'Ein Tag wurde entfernt'
    end

    it 'removes zero tags and displays flash message' do
      expect(tag_list_double).to receive(:remove).and_return(0)
      post :destroy, params: { group_id: group.id, ids: leader.id, tags: 'existing' }
      expect(flash[:notice]).to include 'Es wurden keine Tags entfernt'
    end

    it 'removes many tags and displays flash message' do
      expect(tag_list_double).to receive(:remove).and_return(17)
      post :destroy, params: { group_id: group.id, ids: leader.id, tags: 'existing' }
      expect(flash[:notice]).to include '17 Tags wurden entfernt'
    end
  end

end
