# typed: strict
class Domain::Inkbunny::Job::LatestPostsJob < Domain::Inkbunny::Job::Base
  ApiSearchPageProcessor = Domain::Inkbunny::Job::ApiSearchPageProcessor

  sig { override.params(args: T::Hash[Symbol, T.untyped]).returns(T.untyped) }
  def perform(args)
    processor = ApiSearchPageProcessor.new
    first_log_entry = nil
    rid = T.let(nil, T.nilable(String))
    page = T.let(1, Integer)
    loop_count = T.let(0, Integer)

    while true
      loop_count += 1
      if loop_count > ApiSearchPageProcessor::MAX_PAGE_COUNT
        fatal_error("loop_count > #{ApiSearchPageProcessor::MAX_PAGE_COUNT}")
      end

      url = ApiSearchPageProcessor.build_api_search_url(rid: rid, page: page)
      response = http_client.post(url)

      if response.status_code != 200
        fatal_error("api_search failed: #{response.status_code}")
      end

      result =
        processor.process!(
          JSON.parse(response.body),
          caused_by_entry: response.log_entry,
        )
      num_new_posts = T.cast(result[:num_new_posts], Integer)
      logger.info(
        [
          "[rid: #{rid}]",
          "[page #{page}]",
          "[new posts: #{num_new_posts}]",
          "[total changed posts: #{result[:num_total_changed_posts]}]",
          "[total changed users: #{result[:num_total_changed_users]}]",
          "[total posts: #{result[:num_total_posts]}]",
          "[total users: #{result[:num_total_users]}]",
        ].join(" "),
      )
      if num_new_posts < ApiSearchPageProcessor::SUBMISSIONS_PER_PAGE
        logger.info("[no new posts, stopping]")
        break
      end
      rid ||= T.cast(result[:rid], String)
      page += 1
    end

    processor.all_users.each do |user|
      if user.due_for_gallery_scan?
        defer_job(
          Domain::Inkbunny::Job::UserGalleryJob,
          { user: user, caused_by_entry: first_log_entry },
          { priority: 2 },
        )
      end
    end

    posts_to_update = processor.all_posts.reject(&:deep_updated_at)
    if posts_to_update.any?
      defer_job(
        Domain::Inkbunny::Job::UpdatePostsJob,
        {
          ib_post_ids: posts_to_update.map(&:ib_id),
          caused_by_entry: first_log_entry,
        },
      )
    end
  end
end
