# Responsible for generating the asynchronus data of a user.  This is data that we send on the wire
# to the application for much of its user specific client-side rendering.
#
# @see AsyncInfoController#user_data
# @see UserDecorator
# @see ApplicationPolicy
class AsyncInfo
  include FieldTest::Helpers
  # @api public
  #
  # Generate a Hash of the relevant user data.
  #
  # @param user [User, UserDecorator]
  # @param context [ApplicationController]
  # @return [Hash<Symbol,Object>]
  #
  # @see ApplicationController#feed_style_preference
  #
  # @todo The given feed_style_prefernce could be extracted to the user decorator.  We would need to
  #       account for a nil current user in our view logic.
  def self.to_hash(user:, context:)
    new(user: user, context: context).to_hash
  end

  def initialize(user:, context:)
    @user = user.decorate
    @context = context
  end

  attr_reader :user, :context

  def to_hash
    {
      id: user.id,
      name: user.name,
      username: user.username,
      profile_image_90: user.profile_image_url_for(length: 90),
      followed_tags: user.cached_followed_tags.to_json,
      followed_podcast_ids: user.cached_following_podcasts_ids,
      reading_list_ids: user.cached_reading_list_article_ids,
      blocked_user_ids: UserBlock.cached_blocked_ids_for_blocker(user.id),
      saw_onboarding: user.saw_onboarding,
      checked_code_of_conduct: user.checked_code_of_conduct,
      checked_terms_and_conditions: user.checked_terms_and_conditions,
      display_sponsors: user.display_sponsors,
      display_announcements: user.display_announcements,
      trusted: user.trusted?,
      moderator_for_tags: user.moderator_for_tags,
      config_body_class: user.config_body_class,
      feed_style: feed_style_preference_variable(user),
      created_at: user.created_at,
      admin: user.any_admin?,
      ordered_subforem_ids: user.ordered_subforems,
      policies: [
        {
          dom_class: ApplicationPolicy.base_dom_class_for(record: Article, query: :create?),
          visible: visible?(record: Article, query: :create?)
        },
        {
          dom_class: ApplicationPolicy.base_dom_class_for(record: Article, query: :moderate?),
          visible: visible?(record: Article, query: :moderate?)
        },
      ],
      apple_auth: user.email.to_s.end_with?("@privaterelay.appleid.com")
    }
  end

  private

  delegate :feed_style_preference, to: :context

  # @return [TrueClass] if policy allows the given query on the given record
  # @return [FalseClass] if policy raises Pundit::NotAuthorizedError
  # @return [FalseClass] if policy does not allow the given query on the given record
  def visible?(record:, query:)
    context.__send__(:policy, record).public_send(query)
  rescue Pundit::NotAuthorizedError
    false
  end

  def feed_style_preference_variable(user)
    # TODO: Let users set their own feed style preference
    # Currently only at app level

    feed_style_preference
  end
end
