defmodule Mv.Authorization.PermissionSetsTest do
  @moduledoc """
  Tests for the PermissionSets module that defines hardcoded permission sets.
  """
  use ExUnit.Case, async: true

  alias Mv.Authorization.PermissionSets

  describe "all_permission_sets/0" do
    test "returns all four permission sets" do
      sets = PermissionSets.all_permission_sets()

      assert length(sets) == 4
      assert :own_data in sets
      assert :read_only in sets
      assert :normal_user in sets
      assert :admin in sets
    end
  end

  describe "get_permissions/1" do
    test "all permission sets return map with :resources and :pages keys" do
      for set <- PermissionSets.all_permission_sets() do
        permissions = PermissionSets.get_permissions(set)

        assert Map.has_key?(permissions, :resources),
               "#{set} missing :resources key"

        assert Map.has_key?(permissions, :pages),
               "#{set} missing :pages key"

        assert is_list(permissions.resources),
               "#{set} :resources must be a list"

        assert is_list(permissions.pages),
               "#{set} :pages must be a list"
      end
    end

    test "each resource permission has required keys" do
      permissions = PermissionSets.get_permissions(:own_data)

      Enum.each(permissions.resources, fn perm ->
        assert Map.has_key?(perm, :resource)
        assert Map.has_key?(perm, :action)
        assert Map.has_key?(perm, :scope)
        assert Map.has_key?(perm, :granted)
        assert is_binary(perm.resource)
        assert perm.action in [:read, :create, :update, :destroy]
        assert perm.scope in [:own, :linked, :all]
        assert is_boolean(perm.granted)
      end)
    end

    test "pages lists are non-empty for all permission sets" do
      for set <- [:own_data, :read_only, :normal_user, :admin] do
        permissions = PermissionSets.get_permissions(set)

        assert not Enum.empty?(permissions.pages),
               "Permission set #{set} should have at least one page"
      end
    end
  end

  describe "get_permissions/1 - :own_data permission content" do
    test "allows User read/update with scope :own" do
      permissions = PermissionSets.get_permissions(:own_data)

      user_read =
        Enum.find(permissions.resources, fn p -> p.resource == "User" && p.action == :read end)

      user_update =
        Enum.find(permissions.resources, fn p -> p.resource == "User" && p.action == :update end)

      assert user_read.scope == :own
      assert user_read.granted == true
      assert user_update.scope == :own
      assert user_update.granted == true
    end

    test "allows Member read/update with scope :linked" do
      permissions = PermissionSets.get_permissions(:own_data)

      member_read =
        Enum.find(permissions.resources, fn p -> p.resource == "Member" && p.action == :read end)

      member_update =
        Enum.find(permissions.resources, fn p -> p.resource == "Member" && p.action == :update end)

      assert member_read.scope == :linked
      assert member_read.granted == true
      assert member_update.scope == :linked
      assert member_update.granted == true
    end

    test "allows CustomFieldValue read/update with scope :linked" do
      permissions = PermissionSets.get_permissions(:own_data)

      cfv_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :read
        end)

      cfv_update =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :update
        end)

      assert cfv_read.scope == :linked
      assert cfv_read.granted == true
      assert cfv_update.scope == :linked
      assert cfv_update.granted == true
    end

    test "allows CustomField read with scope :all" do
      permissions = PermissionSets.get_permissions(:own_data)

      cf_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomField" && p.action == :read
        end)

      assert cf_read.scope == :all
      assert cf_read.granted == true
    end

    test "includes correct pages" do
      permissions = PermissionSets.get_permissions(:own_data)

      # Root "/" is not allowed for own_data (Mitglied is redirected to profile)
      refute "/" in permissions.pages
      # Profile is at /users/:id, not a separate /profile route
      assert "/users/:id" in permissions.pages
      assert "/members/:id" in permissions.pages
    end
  end

  describe "get_permissions/1 - :read_only permission content" do
    test "allows User read/update with scope :own" do
      permissions = PermissionSets.get_permissions(:read_only)

      user_read =
        Enum.find(permissions.resources, fn p -> p.resource == "User" && p.action == :read end)

      user_update =
        Enum.find(permissions.resources, fn p -> p.resource == "User" && p.action == :update end)

      assert user_read.scope == :own
      assert user_read.granted == true
      assert user_update.scope == :own
      assert user_update.granted == true
    end

    test "allows Member read with scope :all" do
      permissions = PermissionSets.get_permissions(:read_only)

      member_read =
        Enum.find(permissions.resources, fn p -> p.resource == "Member" && p.action == :read end)

      assert member_read.scope == :all
      assert member_read.granted == true
    end

    test "does NOT allow Member create/update/destroy" do
      permissions = PermissionSets.get_permissions(:read_only)

      member_create =
        Enum.find(permissions.resources, fn p -> p.resource == "Member" && p.action == :create end)

      member_update =
        Enum.find(permissions.resources, fn p -> p.resource == "Member" && p.action == :update end)

      member_destroy =
        Enum.find(permissions.resources, fn p ->
          p.resource == "Member" && p.action == :destroy
        end)

      assert member_create == nil || member_create.granted == false
      assert member_update == nil || member_update.granted == false
      assert member_destroy == nil || member_destroy.granted == false
    end

    test "allows CustomFieldValue read with scope :all" do
      permissions = PermissionSets.get_permissions(:read_only)

      cfv_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :read
        end)

      assert cfv_read.scope == :all
      assert cfv_read.granted == true
    end

    test "does NOT allow CustomFieldValue create/update/destroy" do
      permissions = PermissionSets.get_permissions(:read_only)

      cfv_create =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :create
        end)

      cfv_update =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :update
        end)

      cfv_destroy =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :destroy
        end)

      assert cfv_create == nil || cfv_create.granted == false
      assert cfv_update == nil || cfv_update.granted == false
      assert cfv_destroy == nil || cfv_destroy.granted == false
    end

    test "allows CustomField read with scope :all" do
      permissions = PermissionSets.get_permissions(:read_only)

      cf_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomField" && p.action == :read
        end)

      assert cf_read.scope == :all
      assert cf_read.granted == true
    end

    test "includes correct pages" do
      permissions = PermissionSets.get_permissions(:read_only)

      assert "/" in permissions.pages
      assert "/users/:id" in permissions.pages
      assert "/members" in permissions.pages
      assert "/members/:id" in permissions.pages
      assert "/custom_field_values" in permissions.pages
      assert "/custom_field_values/:id" in permissions.pages
    end
  end

  describe "get_permissions/1 - :normal_user permission content" do
    test "allows User read/update with scope :own" do
      permissions = PermissionSets.get_permissions(:normal_user)

      user_read =
        Enum.find(permissions.resources, fn p -> p.resource == "User" && p.action == :read end)

      user_update =
        Enum.find(permissions.resources, fn p -> p.resource == "User" && p.action == :update end)

      assert user_read.scope == :own
      assert user_read.granted == true
      assert user_update.scope == :own
      assert user_update.granted == true
    end

    test "allows Member read/create/update with scope :all" do
      permissions = PermissionSets.get_permissions(:normal_user)

      member_read =
        Enum.find(permissions.resources, fn p -> p.resource == "Member" && p.action == :read end)

      member_create =
        Enum.find(permissions.resources, fn p -> p.resource == "Member" && p.action == :create end)

      member_update =
        Enum.find(permissions.resources, fn p -> p.resource == "Member" && p.action == :update end)

      assert member_read.scope == :all
      assert member_read.granted == true
      assert member_create.scope == :all
      assert member_create.granted == true
      assert member_update.scope == :all
      assert member_update.granted == true
    end

    test "does NOT allow Member destroy (safety)" do
      permissions = PermissionSets.get_permissions(:normal_user)

      member_destroy =
        Enum.find(permissions.resources, fn p ->
          p.resource == "Member" && p.action == :destroy
        end)

      assert member_destroy == nil || member_destroy.granted == false
    end

    test "allows CustomFieldValue full CRUD with scope :all" do
      permissions = PermissionSets.get_permissions(:normal_user)

      cfv_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :read
        end)

      cfv_create =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :create
        end)

      cfv_update =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :update
        end)

      cfv_destroy =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :destroy
        end)

      assert cfv_read.scope == :all
      assert cfv_read.granted == true
      assert cfv_create.scope == :all
      assert cfv_create.granted == true
      assert cfv_update.scope == :all
      assert cfv_update.granted == true
      assert cfv_destroy.scope == :all
      assert cfv_destroy.granted == true
    end

    test "allows CustomField read with scope :all" do
      permissions = PermissionSets.get_permissions(:normal_user)

      cf_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomField" && p.action == :read
        end)

      assert cf_read.scope == :all
      assert cf_read.granted == true
    end

    test "includes correct pages" do
      permissions = PermissionSets.get_permissions(:normal_user)

      assert "/" in permissions.pages
      assert "/users/:id" in permissions.pages
      assert "/members" in permissions.pages
      assert "/members/new" in permissions.pages
      assert "/members/:id" in permissions.pages
      assert "/members/:id/edit" in permissions.pages
      assert "/custom_field_values" in permissions.pages
      assert "/custom_field_values/:id" in permissions.pages
      assert "/custom_field_values/new" in permissions.pages
      assert "/custom_field_values/:id/edit" in permissions.pages
    end
  end

  describe "get_permissions/1 - :admin permission content" do
    test "allows User full CRUD with scope :all" do
      permissions = PermissionSets.get_permissions(:admin)

      user_read =
        Enum.find(permissions.resources, fn p -> p.resource == "User" && p.action == :read end)

      user_create =
        Enum.find(permissions.resources, fn p -> p.resource == "User" && p.action == :create end)

      user_update =
        Enum.find(permissions.resources, fn p -> p.resource == "User" && p.action == :update end)

      user_destroy =
        Enum.find(permissions.resources, fn p -> p.resource == "User" && p.action == :destroy end)

      assert user_read.scope == :all
      assert user_read.granted == true
      assert user_create.scope == :all
      assert user_create.granted == true
      assert user_update.scope == :all
      assert user_update.granted == true
      assert user_destroy.scope == :all
      assert user_destroy.granted == true
    end

    test "allows Member full CRUD with scope :all" do
      permissions = PermissionSets.get_permissions(:admin)

      member_read =
        Enum.find(permissions.resources, fn p -> p.resource == "Member" && p.action == :read end)

      member_create =
        Enum.find(permissions.resources, fn p -> p.resource == "Member" && p.action == :create end)

      member_update =
        Enum.find(permissions.resources, fn p -> p.resource == "Member" && p.action == :update end)

      member_destroy =
        Enum.find(permissions.resources, fn p ->
          p.resource == "Member" && p.action == :destroy
        end)

      assert member_read.scope == :all
      assert member_read.granted == true
      assert member_create.scope == :all
      assert member_create.granted == true
      assert member_update.scope == :all
      assert member_update.granted == true
      assert member_destroy.scope == :all
      assert member_destroy.granted == true
    end

    test "allows CustomFieldValue full CRUD with scope :all" do
      permissions = PermissionSets.get_permissions(:admin)

      cfv_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :read
        end)

      cfv_create =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :create
        end)

      cfv_update =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :update
        end)

      cfv_destroy =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomFieldValue" && p.action == :destroy
        end)

      assert cfv_read.scope == :all
      assert cfv_read.granted == true
      assert cfv_create.scope == :all
      assert cfv_create.granted == true
      assert cfv_update.scope == :all
      assert cfv_update.granted == true
      assert cfv_destroy.scope == :all
      assert cfv_destroy.granted == true
    end

    test "allows CustomField full CRUD with scope :all" do
      permissions = PermissionSets.get_permissions(:admin)

      cf_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomField" && p.action == :read
        end)

      cf_create =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomField" && p.action == :create
        end)

      cf_update =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomField" && p.action == :update
        end)

      cf_destroy =
        Enum.find(permissions.resources, fn p ->
          p.resource == "CustomField" && p.action == :destroy
        end)

      assert cf_read.scope == :all
      assert cf_read.granted == true
      assert cf_create.scope == :all
      assert cf_create.granted == true
      assert cf_update.scope == :all
      assert cf_update.granted == true
      assert cf_destroy.scope == :all
      assert cf_destroy.granted == true
    end

    test "allows Role full CRUD with scope :all" do
      permissions = PermissionSets.get_permissions(:admin)

      role_read =
        Enum.find(permissions.resources, fn p -> p.resource == "Role" && p.action == :read end)

      role_create =
        Enum.find(permissions.resources, fn p -> p.resource == "Role" && p.action == :create end)

      role_update =
        Enum.find(permissions.resources, fn p -> p.resource == "Role" && p.action == :update end)

      role_destroy =
        Enum.find(permissions.resources, fn p -> p.resource == "Role" && p.action == :destroy end)

      assert role_read.scope == :all
      assert role_read.granted == true
      assert role_create.scope == :all
      assert role_create.granted == true
      assert role_update.scope == :all
      assert role_update.granted == true
      assert role_destroy.scope == :all
      assert role_destroy.granted == true
    end

    test "has wildcard page permission" do
      permissions = PermissionSets.get_permissions(:admin)

      assert "*" in permissions.pages
    end

    test "admin pages include explicit /settings and /membership_fee_settings" do
      permissions = PermissionSets.get_permissions(:admin)

      assert "/settings" in permissions.pages
      assert "/membership_fee_settings" in permissions.pages
    end
  end

  describe "get_permissions/1 - MemberGroup resource" do
    test "own_data has MemberGroup read with scope :linked only" do
      permissions = PermissionSets.get_permissions(:own_data)

      mg_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MemberGroup" && p.action == :read
        end)

      mg_create =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MemberGroup" && p.action == :create
        end)

      assert mg_read != nil
      assert mg_read.scope == :linked
      assert mg_read.granted == true
      assert mg_create == nil || mg_create.granted == false
    end

    test "read_only has MemberGroup read with scope :all, no create/destroy" do
      permissions = PermissionSets.get_permissions(:read_only)

      mg_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MemberGroup" && p.action == :read
        end)

      mg_create =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MemberGroup" && p.action == :create
        end)

      mg_destroy =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MemberGroup" && p.action == :destroy
        end)

      assert mg_read != nil
      assert mg_read.scope == :all
      assert mg_read.granted == true
      assert mg_create == nil || mg_create.granted == false
      assert mg_destroy == nil || mg_destroy.granted == false
    end

    test "normal_user has MemberGroup read/create/destroy with scope :all" do
      permissions = PermissionSets.get_permissions(:normal_user)

      mg_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MemberGroup" && p.action == :read
        end)

      mg_create =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MemberGroup" && p.action == :create
        end)

      mg_destroy =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MemberGroup" && p.action == :destroy
        end)

      assert mg_read != nil
      assert mg_read.scope == :all
      assert mg_read.granted == true
      assert mg_create != nil
      assert mg_create.scope == :all
      assert mg_create.granted == true
      assert mg_destroy != nil
      assert mg_destroy.scope == :all
      assert mg_destroy.granted == true
    end

    test "admin has MemberGroup read/create/destroy with scope :all" do
      permissions = PermissionSets.get_permissions(:admin)

      mg_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MemberGroup" && p.action == :read
        end)

      mg_create =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MemberGroup" && p.action == :create
        end)

      mg_destroy =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MemberGroup" && p.action == :destroy
        end)

      assert mg_read != nil
      assert mg_read.scope == :all
      assert mg_read.granted == true
      assert mg_create != nil
      assert mg_create.granted == true
      assert mg_destroy != nil
      assert mg_destroy.granted == true
    end
  end

  describe "get_permissions/1 - MembershipFeeType resource" do
    test "all permission sets have MembershipFeeType read with scope :all" do
      for set <- PermissionSets.all_permission_sets() do
        permissions = PermissionSets.get_permissions(set)

        mft_read =
          Enum.find(permissions.resources, fn p ->
            p.resource == "MembershipFeeType" && p.action == :read
          end)

        assert mft_read != nil, "Permission set #{set} should have MembershipFeeType read"
        assert mft_read.scope == :all
        assert mft_read.granted == true
      end
    end

    test "only admin has MembershipFeeType create/update/destroy" do
      for set <- [:own_data, :read_only, :normal_user] do
        permissions = PermissionSets.get_permissions(set)

        mft_create =
          Enum.find(permissions.resources, fn p ->
            p.resource == "MembershipFeeType" && p.action == :create
          end)

        mft_update =
          Enum.find(permissions.resources, fn p ->
            p.resource == "MembershipFeeType" && p.action == :update
          end)

        mft_destroy =
          Enum.find(permissions.resources, fn p ->
            p.resource == "MembershipFeeType" && p.action == :destroy
          end)

        assert mft_create == nil || mft_create.granted == false,
               "Permission set #{set} should not allow MembershipFeeType create"

        assert mft_update == nil || mft_update.granted == false,
               "Permission set #{set} should not allow MembershipFeeType update"

        assert mft_destroy == nil || mft_destroy.granted == false,
               "Permission set #{set} should not allow MembershipFeeType destroy"
      end

      admin_permissions = PermissionSets.get_permissions(:admin)

      mft_create =
        Enum.find(admin_permissions.resources, fn p ->
          p.resource == "MembershipFeeType" && p.action == :create
        end)

      mft_update =
        Enum.find(admin_permissions.resources, fn p ->
          p.resource == "MembershipFeeType" && p.action == :update
        end)

      mft_destroy =
        Enum.find(admin_permissions.resources, fn p ->
          p.resource == "MembershipFeeType" && p.action == :destroy
        end)

      assert mft_create != nil
      assert mft_create.scope == :all
      assert mft_create.granted == true
      assert mft_update != nil
      assert mft_update.granted == true
      assert mft_destroy != nil
      assert mft_destroy.granted == true
    end
  end

  describe "get_permissions/1 - MembershipFeeCycle resource" do
    test "all permission sets have MembershipFeeCycle read; own_data uses :linked, others :all" do
      for set <- PermissionSets.all_permission_sets() do
        permissions = PermissionSets.get_permissions(set)

        mfc_read =
          Enum.find(permissions.resources, fn p ->
            p.resource == "MembershipFeeCycle" && p.action == :read
          end)

        assert mfc_read != nil, "Permission set #{set} should have MembershipFeeCycle read"
        assert mfc_read.granted == true

        expected_scope = if set == :own_data, do: :linked, else: :all

        assert mfc_read.scope == expected_scope,
               "Permission set #{set} should have MembershipFeeCycle read scope #{expected_scope}, got #{mfc_read.scope}"
      end
    end

    test "read_only has MembershipFeeCycle read only, no update" do
      permissions = PermissionSets.get_permissions(:read_only)

      mfc_update =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MembershipFeeCycle" && p.action == :update
        end)

      assert mfc_update == nil || mfc_update.granted == false
    end

    test "normal_user has MembershipFeeCycle read/create/update/destroy with scope :all" do
      permissions = PermissionSets.get_permissions(:normal_user)

      mfc_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MembershipFeeCycle" && p.action == :read
        end)

      mfc_create =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MembershipFeeCycle" && p.action == :create
        end)

      mfc_update =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MembershipFeeCycle" && p.action == :update
        end)

      mfc_destroy =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MembershipFeeCycle" && p.action == :destroy
        end)

      assert mfc_read != nil && mfc_read.granted == true
      assert mfc_create != nil && mfc_create.scope == :all && mfc_create.granted == true
      assert mfc_update != nil && mfc_update.granted == true
      assert mfc_destroy != nil && mfc_destroy.scope == :all && mfc_destroy.granted == true
    end

    test "admin has MembershipFeeCycle read/create/update/destroy with scope :all" do
      permissions = PermissionSets.get_permissions(:admin)

      mfc_read =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MembershipFeeCycle" && p.action == :read
        end)

      mfc_create =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MembershipFeeCycle" && p.action == :create
        end)

      mfc_update =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MembershipFeeCycle" && p.action == :update
        end)

      mfc_destroy =
        Enum.find(permissions.resources, fn p ->
          p.resource == "MembershipFeeCycle" && p.action == :destroy
        end)

      assert mfc_read != nil
      assert mfc_read.granted == true
      assert mfc_create != nil
      assert mfc_create.granted == true
      assert mfc_update != nil
      assert mfc_update.granted == true
      assert mfc_destroy != nil
      assert mfc_destroy.granted == true
    end
  end

  describe "valid_permission_set?/1" do
    test "returns true for valid permission set string" do
      assert PermissionSets.valid_permission_set?("own_data") == true
      assert PermissionSets.valid_permission_set?("read_only") == true
      assert PermissionSets.valid_permission_set?("normal_user") == true
      assert PermissionSets.valid_permission_set?("admin") == true
    end

    test "returns true for valid permission set atom" do
      assert PermissionSets.valid_permission_set?(:own_data) == true
      assert PermissionSets.valid_permission_set?(:read_only) == true
      assert PermissionSets.valid_permission_set?(:normal_user) == true
      assert PermissionSets.valid_permission_set?(:admin) == true
    end

    test "returns false for invalid permission set string" do
      assert PermissionSets.valid_permission_set?("invalid") == false
      assert PermissionSets.valid_permission_set?("") == false
      assert PermissionSets.valid_permission_set?("admin_user") == false
    end

    test "returns false for invalid permission set atom" do
      assert PermissionSets.valid_permission_set?(:invalid) == false
      assert PermissionSets.valid_permission_set?(:unknown) == false
    end

    test "returns false for nil input" do
      assert PermissionSets.valid_permission_set?(nil) == false
    end

    test "returns false for invalid types" do
      assert PermissionSets.valid_permission_set?(123) == false
      assert PermissionSets.valid_permission_set?([]) == false
      assert PermissionSets.valid_permission_set?(%{}) == false
      assert PermissionSets.valid_permission_set?("") == false
    end
  end

  describe "permission_set_name_to_atom/1" do
    test "returns {:ok, atom} for valid permission set name" do
      assert PermissionSets.permission_set_name_to_atom("own_data") == {:ok, :own_data}
      assert PermissionSets.permission_set_name_to_atom("read_only") == {:ok, :read_only}
      assert PermissionSets.permission_set_name_to_atom("normal_user") == {:ok, :normal_user}
      assert PermissionSets.permission_set_name_to_atom("admin") == {:ok, :admin}
    end

    test "returns {:error, :invalid_permission_set} for invalid permission set name" do
      assert PermissionSets.permission_set_name_to_atom("invalid") ==
               {:error, :invalid_permission_set}

      assert PermissionSets.permission_set_name_to_atom("") == {:error, :invalid_permission_set}

      assert PermissionSets.permission_set_name_to_atom("admin_user") ==
               {:error, :invalid_permission_set}
    end

    test "handles non-existent atom gracefully" do
      # String.to_existing_atom will raise ArgumentError for non-existent atoms
      assert PermissionSets.permission_set_name_to_atom("nonexistent_atom_12345") ==
               {:error, :invalid_permission_set}
    end
  end

  describe "get_permissions/1 - error handling" do
    test "raises ArgumentError for invalid permission set with helpful message" do
      assert_raise ArgumentError,
                   ~r/invalid permission set: :invalid\. Must be one of:/,
                   fn ->
                     PermissionSets.get_permissions(:invalid)
                   end
    end

    test "error message includes all valid permission sets" do
      error =
        assert_raise ArgumentError, fn ->
          PermissionSets.get_permissions(:unknown)
        end

      error_message = Exception.message(error)
      assert error_message =~ "own_data"
      assert error_message =~ "read_only"
      assert error_message =~ "normal_user"
      assert error_message =~ "admin"
    end
  end
end
