# typed: false
require "rails_helper"

describe Domain::E621::Job::ScanUsersJob do
  let(:http_client_mock) { instance_double("::Scraper::HttpClient") }
  before { Scraper::ClientFactory.http_client_mock = http_client_mock }

  let!(:log_entries) do
    HttpClientMockHelpers.init_http_client_mock(
      http_client_mock,
      [
        {
          uri: "https://e621.net/users.json?limit=320",
          content_type: "application/json",
          contents:
            File.read("test/fixtures/files/domain/e621/job/users_index_0.json"),
        },
        {
          uri: "https://e621.net/users.json?limit=320&page=b2089164",
          content_type: "application/json",
          contents:
            File.read(
              "test/fixtures/files/domain/e621/job/users_index_empty.json",
            ),
          caused_by_entry_idx: 0,
        },
      ],
    )
  end

  it "creates users from the API response" do
    expect { perform_now({}) }.to change(Domain::User::E621User, :count).by(12)

    user = Domain::User::E621User.find_by(e621_id: 2_089_238)
    expect(user).not_to be_nil
    expect(user.name).to eq("chongzi")

    user = Domain::User::E621User.find_by(e621_id: 2_089_235)
    expect(user).not_to be_nil
    expect(user.name).to eq("dhqobc")
  end

  # it "enqueues scan user favs jobs for new users" do
  #   perform_now({})

  #   user1 = Domain::User::E621User.find_by(e621_id: 2_089_238)
  #   user2 = Domain::User::E621User.find_by(e621_id: 2_089_237)

  #   expect(SpecUtil.enqueued_jobs(Domain::E621::Job::ScanUserFavsJob)).to match(
  #     array_including(
  #       including(args: [{ user: user1, caused_by_entry: log_entries[0] }]),
  #       including(args: [{ user: user2, caused_by_entry: log_entries[0] }]),
  #     ),
  #   )
  # end

  context "when user already exists" do
    let!(:existing_user) do
      Domain::User::E621User.create!(e621_id: 2_089_238, name: "chongzi")
    end

    it "does not create duplicate users" do
      expect { perform_now({}) }.to change(Domain::User::E621User, :count).by(
        11,
      )
    end

    # it "does not enqueue scan favs job for existing users" do
    #   perform_now({})

    #   new_user = Domain::User::E621User.find_by(e621_id: 2_089_237)

    #   expect(
    #     SpecUtil.enqueued_jobs(Domain::E621::Job::ScanUserFavsJob),
    #   ).not_to include(
    #     including(
    #       args: [{ user: existing_user, caused_by_entry: log_entries[0] }],
    #     ),
    #   )
    #   expect(
    #     SpecUtil.enqueued_jobs(Domain::E621::Job::ScanUserFavsJob),
    #   ).to include(
    #     including(args: [{ user: new_user, caused_by_entry: log_entries[0] }]),
    #   )
    # end
  end

  context "with pagination" do
    let(:log_entries) do
      HttpClientMockHelpers.init_http_client_mock(
        http_client_mock,
        [
          {
            uri: "https://e621.net/users.json?limit=320",
            content_type: "application/json",
            contents:
              File.read(
                "test/fixtures/files/domain/e621/job/users_index_0.json",
              ),
          },
          {
            uri: "https://e621.net/users.json?limit=320&page=b2089164",
            content_type: "application/json",
            contents:
              File.read(
                "test/fixtures/files/domain/e621/job/users_index_1.json",
              ),
            caused_by_entry_idx: 0,
          },
          {
            uri: "https://e621.net/users.json?limit=320&page=b2089089",
            content_type: "application/json",
            contents:
              File.read(
                "test/fixtures/files/domain/e621/job/users_index_empty.json",
              ),
            caused_by_entry_idx: 0,
          },
        ],
      )
    end

    it "follows pagination and creates all users" do
      expect { perform_now({}) }.to change(Domain::User::E621User, :count).by(
        23,
      )

      # First page
      expect(Domain::User::E621User.exists?(e621_id: 2_089_238)).to be true
      expect(Domain::User::E621User.exists?(e621_id: 2_089_235)).to be true

      # Second page
      expect(Domain::User::E621User.exists?(e621_id: 2_089_163)).to be true
      expect(Domain::User::E621User.exists?(e621_id: 2_089_091)).to be true
    end
  end

  context "when API returns error" do
    let(:log_entries) do
      HttpClientMockHelpers.init_http_client_mock(
        http_client_mock,
        [
          {
            method: :get,
            uri: "https://e621.net/users.json?limit=320",
            content_type: "application/json",
            status_code: 500,
            contents: "Internal Server Error",
          },
        ],
      )
    end

    it "raises an error" do
      expect { perform_now({}) }.to raise_error(/non 200 response/)
    end
  end
end
