#  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 RoleListsController do
  before { sign_in(people(:top_leader)) }

  let(:group) { groups(:top_group) }
  let(:person1) { role1.person }
  let(:person2) { role2.person }
  let!(:role1) { Fabricate(Group::TopGroup::Member.name.to_sym, group: group) }
  let!(:role2) { Fabricate(Group::TopGroup::Leader.name.to_sym, group: group) }

  context "authorization" do
    before do
      sign_in(people(:bottom_member))
    end

    it "GET#move initializes entry so form extensions can rely on it" do
      get :move, xhr: true, params: {group_id: group.id, ids: [roles(:bottom_member).id]}, format: :js
      expect(assigns(:role)).to be_present
    end

    it "GET#moveable initializes entry" do
      role_params = {group_id: group.id, type: "Group::BottomLayer::Member", label: "dummy"}
      get :movable, xhr: true, params: {group_id: group.id, ids: [roles(:bottom_member).id], role: role_params},
        format: :js
      expect(assigns(:role)).to be_present
      expect(assigns(:role).label).to eq "dummy"
    end

    it "PUT update" do
      expect do
        put :update, params: {
          group_id: group,
          ids: person1.id,
          moving_role_type: Group::TopGroup::Member,
          role: {type: Group::TopGroup::Leader,
                 group_id: group}
        }
      end.not_to change(Group::TopGroup::Leader, :count)

      expect(flash[:alert]).to include "Zugriff auf #{person1.full_name} verweigert"
    end

    it "DELETE destroy" do
      expect do
        delete :destroy, params: {
          group_id: group,
          ids: person1.id,
          role: {types: {Group::TopGroup::Member => 1}}
        }
      end.not_to change(Role, :count)

      expect(flash[:alert]).to include "Zugriff auf #{person1.full_name} verweigert"
    end

    it "POST create" do
      expect do
        post :create, params: {
          group_id: group,
          ids: person1.id,
          role: {type: Group::TopGroup::Member,
                 group_id: group}
        }
      end.not_to change(Role, :count)

      expect(flash[:alert]).to include "Zugriff auf #{person1.full_name} verweigert"
    end
  end

  context "DELETE destroy" do
    it "only removes one role" do
      expect do
        delete :destroy, params: {
          group_id: group,
          ids: person1.id,
          role: {types: {Group::TopGroup::Member => 1}}
        }
      end.to change(Role, :count).by(-1)

      expect(flash[:notice]).to include "Eine Rolle wurde entfernt"
    end

    it "may remove multiple roles" do
      expect do
        delete :destroy, params: {
          group_id: group,
          ids: [person1.id, person2.id].join(","),
          role: {types: {Group::TopGroup::Member => 1,
                         Group::TopGroup::Leader => 1}}
        }
      end.to change(Role, :count).by(-2)

      expect(flash[:notice]).to include "2 Rollen wurden entfernt"
    end
  end

  context "POST create" do
    it "creates only one role for one person" do
      expect do
        post :create, params: {
          group_id: group,
          ids: person1.id,
          role: {type: Group::TopGroup::Member,
                 group_id: group}
        }
      end.to change(Role, :count).by(1)

      expect(flash[:notice]).to include "Eine Rolle wurde erstellt"
    end

    it "may create multiple roles" do
      expect do
        post :create, params: {
          group_id: group,
          ids: [person2.id, person1.id].join(","),
          role: {type: Group::TopGroup::Member,
                 group_id: group}
        }
      end.to change(Role, :count).by(2)

      expect(flash[:notice]).to include "2 Rollen wurden erstellt"
    end

    it "may create multiple roles in another group" do
      expect do
        post :create, params: {
          group_id: group,
          ids: [person2.id, person1.id].join(","),
          role: {type: Group::TopLayer::TopAdmin,
                 group_id: groups(:top_layer)}
        }
      end.to change(Group::TopLayer::TopAdmin, :count).by(2)

      expect(flash[:notice]).to include "2 Rollen wurden erstellt"
      expect(person1.roles.count).to eq(2)
      expect(person2.roles.count).to eq(2)
    end
  end

  context "PUT update" do
    it "fails on invalid role type" do
      put :update, params: {
        group_id: group,
        ids: person1.id,
        moving_role_type: Group::TopGroup::Member,
        role: {type: "invalid",
               group_id: group}
      }

      expect(flash[:alert]).to include "Bitte geben Sie eine valide Rolle an"
    end

    it "change role type of one role" do
      put :update, params: {
        group_id: group,
        ids: person1.id,
        role: {types: {Group::TopGroup::Member => 1},
               type: Group::TopGroup::Leader,
               group_id: group}
      }

      role = person1.roles.first
      expect(role.group).to eq(group)
      expect(role.type).to eq("Group::TopGroup::Leader")
    end

    it "may change multiple role types" do
      put :update, params: {
        group_id: group,
        ids: [person1.id, person2.id].join(","),
        role: {types: {Group::TopGroup::Member => 1,
                       Group::TopGroup::Leader => 1},
               type: Group::TopGroup::Leader,
               group_id: group}
      }

      role1 = person1.roles.first
      role2 = person2.roles.first

      [role1, role2].each do |role|
        expect(role.group).to eq(group)
        expect(role.type).to eq("Group::TopGroup::Leader")
      end
    end

    it "may move multiple roles into another group and changes type" do
      put :update, params: {
        group_id: group,
        ids: [person1.id, person2.id].join(","),
        role: {types: {Group::TopGroup::Member => 1,
                       Group::TopGroup::Leader => 1},
               type: Group::TopLayer::TopAdmin,
               group_id: groups(:top_layer)}
      }

      role1 = person1.roles.first
      role2 = person2.roles.first

      [role1, role2].each do |role|
        expect(role.group).to eq(groups(:top_layer))
        expect(role.type).to eq("Group::TopLayer::TopAdmin")
      end
    end
  end
end
