# typed: false
require "rails_helper"

RSpec.describe State::IpAddressRolesController, type: :controller do
  let(:user) { create(:user, :admin) }
  let(:ip_address_role) { create(:ip_address_role, active: true) }

  before { sign_in user }

  describe "GET #index" do
    it "returns a success response" do
      get :index
      expect(response).to be_successful
    end

    it "orders ip address roles by created_at desc" do
      older_role = create(:ip_address_role, created_at: 2.days.ago)
      newer_role = create(:ip_address_role, created_at: 1.day.ago)

      get :index
      expect(assigns(:ip_address_roles)).to eq([newer_role, older_role])
    end
  end

  describe "GET #new" do
    it "returns a success response" do
      get :new
      expect(response).to be_successful
    end
  end

  describe "GET #edit" do
    it "returns a success response" do
      get :edit, params: { id: ip_address_role.id }
      expect(response).to be_successful
    end
  end

  describe "POST #create" do
    context "with valid params" do
      let(:valid_attributes) do
        {
          ip_address: "192.168.1.0/24",
          role: "user",
          description: "Test role",
          active: true,
        }
      end

      it "creates a new IpAddressRole" do
        expect {
          post :create, params: { ip_address_role: valid_attributes }
        }.to change(IpAddressRole, :count).by(1)
      end

      it "redirects to the ip_address_roles list" do
        post :create, params: { ip_address_role: valid_attributes }
        expect(response).to redirect_to(state_ip_address_roles_path)
      end
    end

    context "with invalid params" do
      let(:invalid_attributes) { { ip_address: "", role: "user" } }

      it "returns a success response (i.e. to display the 'new' template)" do
        post :create, params: { ip_address_role: invalid_attributes }
        expect(response).to be_successful
      end
    end
  end

  describe "PUT #update" do
    context "with valid params" do
      let(:new_attributes) do
        { description: "Updated description", active: false }
      end

      it "updates the requested ip_address_role" do
        put :update,
            params: {
              id: ip_address_role.id,
              ip_address_role: new_attributes,
            }
        ip_address_role.reload
        expect(ip_address_role.description).to eq("Updated description")
        expect(ip_address_role.active).to eq(false)
      end

      it "redirects to the ip_address_roles list" do
        put :update,
            params: {
              id: ip_address_role.id,
              ip_address_role: new_attributes,
            }
        expect(response).to redirect_to(state_ip_address_roles_path)
      end
    end

    context "with invalid params" do
      let(:invalid_attributes) { { ip_address: "" } }

      it "returns a success response (i.e. to display the 'edit' template)" do
        put :update,
            params: {
              id: ip_address_role.id,
              ip_address_role: invalid_attributes,
            }
        expect(response).to be_successful
      end
    end
  end

  describe "DELETE #destroy" do
    it "destroys the requested ip_address_role" do
      ip_address_role # Create the record
      expect { delete :destroy, params: { id: ip_address_role.id } }.to change(
        IpAddressRole,
        :count,
      ).by(-1)
    end

    it "redirects to the ip_address_roles list" do
      delete :destroy, params: { id: ip_address_role.id }
      expect(response).to redirect_to(state_ip_address_roles_path)
    end
  end

  describe "authorization" do
    let(:regular_user) { create(:user, :user) }

    context "with a regular user" do
      before { sign_in regular_user }

      it "denies access to index" do
        get :index
        expect(response).to redirect_to(root_path)
        expect(flash[:alert]).to eq(
          "You are not authorized to perform this action.",
        )
      end

      it "denies access to new" do
        get :new
        expect(response).to redirect_to(root_path)
        expect(flash[:alert]).to eq(
          "You are not authorized to perform this action.",
        )
      end

      it "denies access to create" do
        post :create,
             params: {
               ip_address_role: {
                 ip_address: "192.168.1.0/24",
                 role: "user",
               },
             }
        expect(response).to redirect_to(root_path)
        expect(flash[:alert]).to eq(
          "You are not authorized to perform this action.",
        )
      end

      it "denies access to edit" do
        get :edit, params: { id: ip_address_role.id }
        expect(response).to redirect_to(root_path)
        expect(flash[:alert]).to eq(
          "You are not authorized to perform this action.",
        )
      end

      it "denies access to update" do
        put :update,
            params: {
              id: ip_address_role.id,
              ip_address_role: {
                description: "test",
              },
            }
        expect(response).to redirect_to(root_path)
        expect(flash[:alert]).to eq(
          "You are not authorized to perform this action.",
        )
      end

      it "denies access to destroy" do
        delete :destroy, params: { id: ip_address_role.id }
        expect(response).to redirect_to(root_path)
        expect(flash[:alert]).to eq(
          "You are not authorized to perform this action.",
        )
      end
    end

    context "with no user" do
      before { sign_out :user }

      it "redirects to login for index" do
        get :index
        expect(response).to redirect_to(new_user_session_path)
      end

      it "redirects to login for new" do
        get :new
        expect(response).to redirect_to(new_user_session_path)
      end

      it "redirects to login for create and does not create the role" do
        expect {
          post :create,
               params: {
                 ip_address_role: {
                   ip_address: "192.168.1.0/24",
                   role: "user",
                 },
               }
        }.not_to change(IpAddressRole, :count)
        expect(response).to redirect_to(new_user_session_path)
      end

      it "redirects to login for edit" do
        get :edit, params: { id: ip_address_role.id }
        expect(response).to redirect_to(new_user_session_path)
      end

      it "redirects to login for update and does not update the role" do
        original_description = ip_address_role.description
        put :update,
            params: {
              id: ip_address_role.id,
              ip_address_role: {
                description: "unauthorized update",
              },
            }
        expect(response).to redirect_to(new_user_session_path)
        expect(ip_address_role.reload.description).to eq(original_description)
      end

      it "redirects to login for destroy and does not delete the role" do
        ip_address_role # Create the record
        expect {
          delete :destroy, params: { id: ip_address_role.id }
        }.not_to change(IpAddressRole, :count)
        expect(response).to redirect_to(new_user_session_path)
      end
    end
  end

  describe "PATCH #toggle" do
    context "when user is authorized" do
      before { sign_in user }

      it "toggles the active state" do
        expect { patch :toggle, params: { id: ip_address_role.id } }.to change {
          ip_address_role.reload.active
        }.from(true).to(false)

        expect(response).to redirect_to(state_ip_address_roles_path)
        expect(flash[:notice]).to be_nil
      end
    end

    context "when user is not authorized" do
      let(:regular_user) { create(:user, :user) }
      before { sign_in regular_user }

      it "prevents toggling the active state" do
        patch :toggle, params: { id: ip_address_role.id }
        expect(response).to redirect_to(root_path)
        expect(flash[:alert]).to eq(
          "You are not authorized to perform this action.",
        )
      end

      it "does not update the active state" do
        expect {
          patch :toggle, params: { id: ip_address_role.id }
        }.not_to change { ip_address_role.reload.active }
      end
    end

    context "when user is not authenticated" do
      before { sign_out :user }

      it "redirects to login" do
        patch :toggle, params: { id: ip_address_role.id }
        expect(response).to redirect_to(new_user_session_path)
      end
    end
  end
end
