# app/graphql/concerns/shared_graphql_methods.rb
module SharedGraphqlMethods
  extend ActiveSupport::Concern

  included do
    # Class method to set permission requirements
    def self.require_permission(level = :admin_or_platform_admin)
      @permission_level = level
    end

    # Class method to get permission requirements
    def self.permission_level
      @permission_level || :admin_or_platform_admin # Default to :admin_or_platform_admin
    end

    # Class method to define before hooks
    def self.before_action(*method_names)
      # Initialize the before actions array if it doesn't exist
      @before_actions ||= []
      # Add each method name passed as arguments to the before_actions array
      method_names.each do |method_name|
        @before_actions << method_name unless @before_actions.include?(method_name)
      end
    end

    # Define a placeholder for the return type
    def self.return_type(return_type)
      field :data, return_type, null: true
      field :errors, [String], null: true
      field :message, String, null: false
      field :http_status, Integer, null: false
      field :token, String, null: true
    end
  end

  # Reusable method to check if a record exists by id
  def check_not_found(model_class, id)
    record = model_class.find_by(id: id)
    return failure_response(errors: ["#{model_class.name} not found"]) unless record

    nil # Return nil if no error
  end

  # Run all the before actions
  def run_before_actions(args)
    # Run all the before actions
    self.class.instance_variable_get(:@before_actions)&.each do |method|
      result = send(method, **args)
      return result if result
    end
    nil
  end

  protected

  # Check associated records by detecting *_id attributes
  def check_associated_records(args)
    response = nil
    args.each do |key, value|
      # Check for keys ending with '_id'
      next unless key.to_s.end_with?('_id')

      # Derive the model name from the key (e.g., 'course_id' becomes 'Course')
      model_name = key.to_s.sub('_id', '').camelcase
      model_class = model_name.safe_constantize

      # If the model class exists, check if the record exists
      response = check_not_found(model_class, value) if model_class
    end
    response
  end

  def check_permission(_args={})
    user = context[:current_user]
    permission_level = self.class.permission_level
    permission_checker_method = permission_method_for(permission_level)

    unless PermissionChecker.send(permission_checker_method, user) # rubocop:disable Style/GuardClause
      failure_response(errors: ['Access denied to endpoint'])
    end
  end

  private

  def permission_method_for(level)
    {
      admin_or_platform_admin: :ensure_admin_or_platform_admin!,
      admin: :ensure_admin_only!,
      platform_admin: :ensure_platform_admin_only!,
      ensure_all_groups: :ensure_all_groups!
    }[level]
  end
end 