defmodule Mv.Authorization.Checks.ActorPermissionSetIs do
  @moduledoc """
  Policy check: true when the actor's role has the given permission_set_name.

  Used to restrict bypass policies (e.g. MemberGroup read by member_id) to actors
  with a specific permission set (e.g. "own_data") so that admin with member_id
  still gets :all scope from HasPermission, not the bypass filter.

  ## Usage

      # In a resource policy (both conditions must hold for the bypass)
      bypass action_type(:read) do
        authorize_if expr(member_id == ^actor(:member_id))
        authorize_if {Mv.Authorization.Checks.ActorPermissionSetIs, permission_set_name: "own_data"}
      end

  ## Options

  - `:permission_set_name` (required) - String or atom, e.g. `"own_data"` or `:own_data`
  """
  use Ash.Policy.SimpleCheck

  alias Mv.Authorization.Actor

  @impl true
  def describe(opts) do
    name = opts[:permission_set_name] || "?"
    "actor has permission set #{name}"
  end

  @impl true
  def match?(actor, _context, opts) do
    case opts[:permission_set_name] do
      nil ->
        false

      expected ->
        case Actor.permission_set_name(actor) do
          nil -> false
          actual -> to_string(expected) == to_string(actual)
        end
    end
  end
end
