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

  sig { override.params(args: T::Hash[Symbol, T.untyped]).returns(T.untyped) }
  def perform(args)
    pool = T.let(args[:pool], Domain::PostGroup::InkbunnyPool)
    logger.push_tags(make_arg_tag(pool))

    if (dule = pool.deep_update_log_entry)
      if dule.status_code == 200
        logger.info("pool already deep updated, skipping")
        return
      else
        logger.info(
          format_tags_arr(
            [
              make_arg_tag(dule, name: "last_hle"),
              "retrying pool deep update",
            ].flatten,
          ),
        )
      end
    end

    processor = ApiSearchPageProcessor.new
    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(
          pool_id: pool.ib_id,
          rid: rid,
          page: page,
        )

      response = http_client.post(url)

      pool.deep_update_log_entry = causing_log_entry
      fatal_error("api_search failed") if response.status_code != 200

      result =
        processor.process!(
          JSON.parse(response.body),
          caused_by_entry: response.log_entry,
        )

      rid ||= T.cast(result[:rid], String)

      logger.info(
        format_tags_arr(
          [
            make_tag("rid", rid),
            make_tag("page", page),
            make_tag("total changed posts", result[:num_total_changed_posts]),
            make_tag("total posts", result[:num_total_posts]),
            make_tag("total users", result[:num_total_users]),
          ],
        ),
      )

      break if result[:num_pages] == page
      page += 1
    end

    pool.save!

    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) },
      )
    end
  ensure
    pool.save! if pool
    logger.pop_tags
  end
end
