#  Copyright (c) 2012-2024, Jungwacht Blauring Schweiz. This file is part of
#  hitobito 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 PeopleFiltersController do
  before { sign_in(user) }

  let(:user) { people(:top_leader) }
  let(:group) { groups(:top_group) }
  let(:role_types) { [Group::TopGroup::Leader, Group::TopGroup::Member] }
  let(:role_type_ids) { role_types.collect(&:id) }
  let(:role_type_ids_string) { role_type_ids.join(Person::Filter::Base::ID_URL_SEPARATOR) }
  let(:role_type_names) { role_types.collect(&:sti_name) }

  context "GET new" do
    it "builds entry with group and existing params" do
      get :new, params: {group_id: group.id, filters: {role: {role_type_ids: role_type_ids_string}}}

      filter = assigns(:people_filter)
      expect(filter.group).to eq(group)
      expect(assigns(:qualification_kinds)).to be_present
    end

    context "#possible_tags" do
      it "preloads available tags" do
        get :new, params: {group_id: group.id}
        expect(assigns(:possible_tags)).to eq []
      end

      it "translates invalid e-mail tags" do
        allow(Truemail).to receive(:valid?).and_call_original
        user.update_columns(email: "not-an-email")
        AdditionalEmail
          .new(contactable: user,
            email: "mail@nodomain")
          .save!(validate: false)
        Contactable::EmailValidator.new.validate_people

        get :new, params: {group_id: group.id}
        # rubocop:todo Layout/LineLength
        invalid_email_tags = [["Haupt-E-Mail ungültig", "category_validation:email_primary_invalid", PersonTags::Validation.email_primary_invalid.id],
          # rubocop:enable Layout/LineLength
          ["Weitere E-Mail ungültig", "category_validation:email_additional_invalid",
            PersonTags::Validation.email_additional_invalid.id]]

        tags = assigns(:possible_tags)

        invalid_email_tags.each do |t|
          expect(tags).to include(t)
        end
      end
    end
  end

  context "POST create" do
    it "redirects to show for search" do
      expect do
        post :create, params: {group_id: group.id, filters: {role: {role_type_ids: role_type_ids}}, button: "search"}
      end.not_to change { PeopleFilter.count }

      is_expected.to redirect_to(group_people_path(group, filters: {role: {role_type_ids: role_type_ids_string}},
        range: "deep"))
    end

    it "redirects to show for empty search" do
      expect do
        post :create,
          params: {group_id: group.id, button: "search", people_filter: {},
                   filters: {qualification: {validity: "active"}}}
      end.not_to change { PeopleFilter.count }

      is_expected.to redirect_to(group_people_path(group))
    end

    it "saves filter and redirects to show with save" do
      expect do
        post :create,
          # rubocop:todo Layout/LineLength
          params: {group_id: group.id, filters: {role: {role_type_ids: role_type_ids}}, range: "deep", name: "Test Filter",
                   # rubocop:enable Layout/LineLength
                   button: "save"}
        expect(assigns(:people_filter)).to be_valid
        is_expected.to redirect_to(group_people_path(group, filter_id: assigns(:people_filter).id))
      end.to change { PeopleFilter.count }.by(1)
    end

    context "with read only permissions" do
      before do
        @role = Fabricate(Group::BottomLayer::Member.name.to_sym, group: groups(:bottom_layer_one))
        @person = @role.person
        sign_in(@person)
      end

      let(:group) { @role.group }

      it "redirects to show with search" do
        expect do
          post :create, params: {group_id: group.id, filters: {role: {role_type_ids: role_type_ids}}, button: "search"}
        end.not_to change { PeopleFilter.count }

        is_expected.to redirect_to(group_people_path(group, filters: {role: {role_type_ids: role_type_ids_string}},
          range: "deep"))
      end

      it "is not authorized with save" do
        expect do
          post :create,
            params: {group_id: group.id, filters: {role: {role_type_ids: role_type_ids}}, name: "Test Filter",
                     button: "save"}
        end.to raise_error(CanCan::AccessDenied)
      end
    end
  end
end
