# frozen_string_literal: true

module WebhookUrls
  EVENT_TYPE_TO_JOB_CLASS = {
    'form.started' => SendFormStartedWebhookRequestJob,
    'form.completed' => SendFormCompletedWebhookRequestJob,
    'form.declined' => SendFormDeclinedWebhookRequestJob,
    'form.viewed' => SendFormViewedWebhookRequestJob,
    'submission.created' => SendSubmissionCreatedWebhookRequestJob,
    'submission.completed' => SendSubmissionCompletedWebhookRequestJob,
    'submission.expired' => SendSubmissionExpiredWebhookRequestJob,
    'submission.archived' => SendSubmissionArchivedWebhookRequestJob,
    'template.created' => SendTemplateCreatedWebhookRequestJob,
    'template.updated' => SendTemplateUpdatedWebhookRequestJob,
    'template.archived' => SendTemplateArchivedWebhookRequestJob
  }.freeze

  EVENT_TYPE_ID_KEYS = {
    'form' => 'submitter_id',
    'submission' => 'submission_id',
    'template' => 'template_id'
  }.freeze

  module_function

  def for_account_id(account_id, events)
    events = Array.wrap(events)

    rel = WebhookUrl.where(account_id:)

    event_arel = events.map { |event| Arel::Table.new(:webhook_urls)[:events].matches("%\"#{event}\"%") }.reduce(:or)

    if Docuseal.multitenant? || account_id == 1
      rel.where(event_arel)
    else
      linked_account_rel =
        AccountLinkedAccount.where(linked_account_id: account_id).where.not(account_type: :testing).select(:account_id)

      webhook_urls = rel.or(WebhookUrl.where(account_id: linked_account_rel).where(event_arel))

      account_urls, linked_urls = webhook_urls.partition { |w| w.account_id == account_id }

      account_urls.select { |w| w.events.intersect?(events) }.presence ||
        (account_urls.present? ? WebhookUrl.none : linked_urls)
    end
  end

  def enqueue_events(records, event_type)
    args = []

    id_key = EVENT_TYPE_ID_KEYS.fetch(event_type.split('.').first)

    Array.wrap(records).group_by(&:account_id).each do |account_id, account_records|
      webhook_urls = for_account_id(account_id, event_type)

      account_records.each do |record|
        event_uuid = SecureRandom.uuid

        webhook_urls.each do |webhook_url|
          next unless webhook_url.events.include?(event_type)

          args << [{ id_key => record.id, 'webhook_url_id' => webhook_url.id, 'event_uuid' => event_uuid }]
        end
      end
    end

    Sidekiq::Client.push_bulk('class' => EVENT_TYPE_TO_JOB_CLASS[event_type], 'args' => args)
  end
end
