# frozen_string_literal: true

class ActivityPub::ProcessFeaturedCollectionService
  include JsonLdHelper
  include Lockable
  include Redisable

  ITEMS_LIMIT = 150

  def call(account, json, request_id: nil)
    @account = account
    @json = json
    @request_id = request_id
    return if non_matching_uri_hosts?(@account.uri, @json['id'])
    return unless @json['attributedTo'] == @account.uri

    with_redis_lock("collection:#{@json['id']}") do
      Collection.transaction do
        @collection = @account.collections.find_or_initialize_by(uri: @json['id'])

        @collection.update!(collection_attributes)

        @items = (@json['orderedItems'] || [])[0, ITEMS_LIMIT]
        item_uris = @items.filter_map { |i| value_or_id(i) }
        @collection.collection_items.where.not(uri: item_uris).delete_all
      end

      process_items!
      notify_about_update!

      @collection
    end
  end

  private

  def notify_about_update!
    NotifyOfCollectionUpdateService.new.call(@collection)
  end

  def truncated_summary
    text = @json['summaryMap']&.values&.first || @json['summary'] || ''
    text[0, Collection::DESCRIPTION_LENGTH_HARD_LIMIT]
  end

  def language
    @json['summaryMap']&.keys&.first
  end

  def url
    url = url_to_href(@json['url'], 'text/html')
    return @json['id'] if url.blank? || unsupported_uri_scheme?(url)

    url
  end

  def collection_attributes
    {
      local: false,
      name: (@json['name'] || '')[0, Collection::NAME_LENGTH_HARD_LIMIT],
      description_html: truncated_summary,
      language:,
      sensitive: @json['sensitive'],
      discoverable: @json['discoverable'],
      original_number_of_items: @json['totalItems'] || 0,
      tag_name: @json.dig('topic', 'name'),
      url:,
    }
  end

  def process_items!
    @items.each_with_index do |item_json, index|
      ActivityPub::ProcessFeaturedItemWorker.perform_async(@collection.id, item_json, index + 1, @request_id)
    end
  end
end
