# typed: false
require "rails_helper"

describe Domain::Inkbunny::Job::LatestPostsJob do
  let(:http_client_mock) { instance_double("::Scraper::HttpClient") }
  before { Scraper::ClientFactory.http_client_mock = http_client_mock }
  let(:api_search_url) do
    "https://inkbunny.net/api_search.php?submissions_per_page=100&page=1&get_rid=yes&orderby=create_datetime&keywords=no"
  end

  context "the files do not change in the response" do
    let! :log_entries do
      HttpClientMockHelpers.init_http_client_mock(
        http_client_mock,
        [
          {
            method: :post,
            uri: api_search_url,
            content_type: "application/json",
            contents:
              SpecUtil.read_fixture_file("domain/inkbunny/job/api_search.json"),
          },
        ],
      )
    end

    it "creates posts" do
      expect { perform_now({}) }.to(
        change(Domain::Post::InkbunnyPost, :count)
          .by(3)
          .and(change(Domain::User::InkbunnyUser, :count).by(3))
          .and(change(Domain::PostFile::InkbunnyPostFile, :count).by(0)),
      )

      user_thendyart = Domain::User::InkbunnyUser.find_by!(ib_id: 941_565)
      expect(user_thendyart.name).to eq("ThendyArt")

      user_seff = Domain::User::InkbunnyUser.find_by!(ib_id: 229_331)
      expect(user_seff.name).to eq("Seff")
      expect(user_seff.avatar).to be_nil

      post_3104202 = Domain::Post::InkbunnyPost.find_by!(ib_id: 3_104_202)
      expect(post_3104202.title).to eq("Phantom Touch - Page 25")
      expect(post_3104202.posted_at).to be_within(1.second).of(
        Time.parse("2023-08-27 21:31:40.365597+02"),
      )
      expect(post_3104202.creator).to eq(user_thendyart)
      expect(post_3104202.last_file_updated_at).to be_within(1.second).of(
        Time.parse("2023-08-27 21:30:06.222262+02"),
      )
      expect(post_3104202.num_files).to eq(1)
      expect(post_3104202.rating).to eq("adult")
      expect(post_3104202.submission_type).to eq("comic")
      expect(post_3104202.shallow_updated_at).to be_within(3.seconds).of(
        Time.now,
      )
      expect(post_3104202.shallow_update_log_entry).to eq(log_entries[0])
      expect(post_3104202.deep_updated_at).to be_nil

      user_soulcentinel = Domain::User::InkbunnyUser.find_by!(ib_id: 349_747)
      expect(user_soulcentinel.scanned_gallery_at).to be_nil

      expect(
        SpecUtil.enqueued_job_args(Domain::Inkbunny::Job::UpdatePostsJob),
      ).to match(
        [
          hash_including(
            ib_post_ids: [3_104_202, 3_104_200, 3_104_197],
            caused_by_entry: log_entries[0],
          ),
        ],
      )

      expect(
        SpecUtil.enqueued_job_args(Domain::Inkbunny::Job::UserGalleryJob),
      ).to match(
        [
          hash_including(user: user_thendyart, caused_by_entry: log_entries[0]),
          hash_including(user: user_seff, caused_by_entry: log_entries[0]),
          hash_including(
            user: user_soulcentinel,
            caused_by_entry: log_entries[0],
          ),
        ],
      )
    end
  end

  context "an existing file changed in the response" do
    let! :log_entries do
      HttpClientMockHelpers.init_http_client_mock(
        http_client_mock,
        [
          {
            method: :post,
            uri: api_search_url,
            content_type: "application/json",
            contents:
              SpecUtil.read_fixture_file(
                "domain/inkbunny/job/api_search_1047334_before.json",
              ),
          },
          {
            method: :post,
            uri: api_search_url,
            content_type: "application/json",
            contents:
              SpecUtil.read_fixture_file(
                "domain/inkbunny/job/api_search_1047334_after.json",
              ),
          },
        ],
      )
    end

    it "updates posts and files" do
      expect { perform_now({}) }.to(
        change(Domain::Post::InkbunnyPost, :count).by(1).and(
          change(Domain::User::InkbunnyUser, :count).by(1),
        ),
      )
      post_1047334 = Domain::Post::InkbunnyPost.find_by!(ib_id: 1_047_334)
      expect(post_1047334.title).to eq("Yellow Snake")
      expect(post_1047334.last_file_updated_at).to be_within(1.second).of(
        Time.parse("2016-03-13 22:18:52.32319+01"),
      )

      expect(
        SpecUtil.enqueued_job_args(Domain::Inkbunny::Job::UpdatePostsJob),
      ).to match([including(ib_post_ids: [1_047_334])])
      SpecUtil.clear_enqueued_jobs!(Domain::Inkbunny::Job::UpdatePostsJob)

      # second perform should update the post
      expect { perform_now({}) }.to(
        change(Domain::Post::InkbunnyPost, :count)
          .by(0)
          .and(change(Domain::User::InkbunnyUser, :count).by(0))
          .and(change(Domain::PostFile::InkbunnyPostFile, :count).by(0)),
      )

      post_1047334.reload
      expect(post_1047334.title).to eq("How to Photograph Snakes")
      expect(post_1047334.last_file_updated_at).to be_within(1.second).of(
        Time.parse("2023-09-14 19:07:45.735562+02"),
      )

      expect(
        SpecUtil.enqueued_job_args(Domain::Inkbunny::Job::UpdatePostsJob),
      ).to match([including(ib_post_ids: [1_047_334])])
    end
  end
end
