# typed: false
require "rails_helper"

RSpec.describe Domain::Inkbunny::Job::UserGalleryJob do
  # User ID is for `zaush`, set the wrong name to test that the name is updated
  let!(:user) do
    create(:domain_user_inkbunny_user, name: "the_user", ib_id: 26_540)
  end
  let(:args) { { user: user, caused_by_entry: nil } }
  let(:http_client_mock) { instance_double("::Scraper::HttpClient") }
  before { Scraper::ClientFactory.http_client_mock = http_client_mock }

  describe "#perform" do
    it "skips if user already scanned recently" do
      at = 1.hour.ago
      user.update!(scanned_gallery_at: at)
      perform_now(args)
      expect(user.reload.scanned_gallery_at).to be_within(1.second).of(at)
    end

    it "works with empty submission pages" do
      HttpClientMockHelpers.init_http_client_mock(
        http_client_mock,
        [
          {
            uri:
              "https://inkbunny.net/api_search.php?submissions_per_page=100&page=1&get_rid=yes&orderby=create_datetime&user_id=26540&keywords=no",
            status_code: 200,
            method: :post,
            content_type: "application/json",
            contents:
              SpecUtil.read_fixture_file(
                "domain/inkbunny/job/api_search_empty_submissions.json",
              ),
            caused_by_entry: nil,
          },
        ],
      )

      expect { perform_now(args) }.to(
        change(Domain::Post::InkbunnyPost, :count)
          .by(0)
          .and(change(Domain::PostFile::InkbunnyPostFile, :count).by(0))
          .and(change(Domain::User::InkbunnyUser, :count).by(0)),
      )
    end

    context "when fetching posts" do
      let!(:log_entries) do
        HttpClientMockHelpers.init_http_client_mock(
          http_client_mock,
          [
            {
              uri:
                "https://inkbunny.net/api_search.php?submissions_per_page=100&page=1&get_rid=yes&orderby=create_datetime&user_id=26540&keywords=no",
              status_code: 200,
              method: :post,
              content_type: "application/json",
              contents:
                SpecUtil.read_fixture_file(
                  "domain/inkbunny/job/api_search_zaush_gallery_page_1.json",
                ),
              caused_by_entry: nil,
            },
            {
              uri:
                "https://inkbunny.net/api_search.php?submissions_per_page=100&page=2&rid=8abcdfca27",
              status_code: 200,
              method: :post,
              content_type: "application/json",
              contents:
                SpecUtil.read_fixture_file(
                  "domain/inkbunny/job/api_search_zaush_gallery_page_2.json",
                ),
              caused_by_entry_idx: 0,
            },
          ],
        )
      end

      it "fetches all pages and enqueues update jobs" do
        expect { perform_now(args) }.to(
          change(Domain::Post::InkbunnyPost, :count)
            .by(4)
            .and(change(Domain::PostFile::InkbunnyPostFile, :count).by(0))
            .and(change(Domain::User::InkbunnyUser, :count).by(0)),
        )

        user.reload
        expect(user.name).to eq("Zaush")
        expect(user.scanned_gallery_at).to be_present
        expect(user.posts.count).to eq(4)
        expect(user.shallow_update_log_entry).to eq(log_entries[0])

        post_3507105 = user.posts.find_by(ib_id: 350_7105)
        expect(post_3507105).to be_present
        expect(post_3507105.num_files).to eq(5)
        expect(post_3507105.files.count).to eq(0)
        expect(post_3507105.shallow_update_log_entry).to eq(log_entries[0])
      end
    end

    context "when fetching posts with null last_file_update_datetime" do
      let!(:log_entries) do
        HttpClientMockHelpers.init_http_client_mock(
          http_client_mock,
          [
            {
              uri:
                "https://inkbunny.net/api_search.php?submissions_per_page=100&page=1&get_rid=yes&orderby=create_datetime&user_id=16532&keywords=no",
              status_code: 200,
              method: :post,
              content_type: "application/json",
              contents:
                SpecUtil.read_fixture_file(
                  "domain/inkbunny/job/api_search_null_last_file_update.json",
                ),
              caused_by_entry: nil,
            },
          ],
        )
      end

      let(:user) do
        create(:domain_user_inkbunny_user, name: "the_user", ib_id: 16_532)
      end
      let(:args) { { user: user, caused_by_entry: nil } }

      it "correctly handles posts with a null last_file_update_datetime",
         quiet: false do
        expect { perform_now(args) }.to(
          change(Domain::Post::InkbunnyPost, :count).by(1),
        )

        user.reload
        expect(user.name).to eq("Darkwitt")
        expect(user.scanned_gallery_at).to be_present
        expect(user.posts.count).to eq(1)
        expect(user.shallow_update_log_entry).to eq(log_entries[0])

        post_2855990 = user.posts.find_by(ib_id: 2_855_990)
        expect(post_2855990).to be_present
        expect(post_2855990.num_files).to eq(0)
        expect(post_2855990.files.count).to eq(0)
        expect(post_2855990.shallow_update_log_entry).to eq(log_entries[0])
      end
    end
  end
end
