# typed: false
require "rails_helper"

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

  let (:post) do
    create(:domain_post_e621_post)
  end

  let(:post_file) do
    create(
      :domain_post_file,
      post: post,
      url_str:
        "https://static1.e621.net/data/c0/fa/c0fa5293f1d1440c2d3f2c3e027d3c36.jpg",
    )
  end

  it "downloads the file" do
    mock_log_entries =
      HttpClientMockHelpers.init_http_client_mock(
        http_client_mock,
        [
          {
            uri:
              "https://static1.e621.net/data/c0/fa/c0fa5293f1d1440c2d3f2c3e027d3c36.jpg",
            status_code: 200,
            content_type: "image/jpeg",
            contents: "test",
          },
        ],
      )

    perform_now({ post_file: post_file })
    post_file.reload
    expect(post_file.state).to eq("ok")
    expect(post_file.log_entry).to eq(mock_log_entries[0])
  end

  it "handles a 404" do
    mock_log_entries =
      HttpClientMockHelpers.init_http_client_mock(
        http_client_mock,
        [
          {
            uri:
              "https://static1.e621.net/data/c0/fa/c0fa5293f1d1440c2d3f2c3e027d3c36.jpg",
            status_code: 404,
            content_type: "text/html",
            contents: "test",
          },
        ],
      )

    perform_now({ post_file: post_file })
    post_file.reload
    expect(post_file.state).to eq("terminal_error")
    expect(post_file.log_entry).to eq(mock_log_entries[0])
    expect(post_file.last_status_code).to eq(404)
    expect(post_file.retry_count).to eq(0)
  end

  it "retries with a retryable error" do
    mock_log_entries =
      HttpClientMockHelpers.init_http_client_mock(
        http_client_mock,
        [
          {
            uri:
              "https://static1.e621.net/data/c0/fa/c0fa5293f1d1440c2d3f2c3e027d3c36.jpg",
            status_code: 500,
            content_type: "text/html",
            contents: "test",
          },
        ],
      )

    perform_now({ post_file: post_file }, should_raise: /will retry later/)
    post_file.reload
    expect(post_file.state).to eq("retryable_error")
    expect(post_file.log_entry).to eq(mock_log_entries[0])
    expect(post_file.last_status_code).to eq(500)
    expect(post_file.retry_count).to eq(1)
  end

  it "gives up after 3 retries" do
    mock_log_entries =
      HttpClientMockHelpers.init_http_client_mock(
        http_client_mock,
        [
          {
            uri:
              "https://static1.e621.net/data/c0/fa/c0fa5293f1d1440c2d3f2c3e027d3c36.jpg",
            status_code: 500,
            content_type: "text/html",
            contents: "test",
          },
        ] * 3,
      )

    perform_now({ post_file: post_file }, should_raise: /will retry later/)
    perform_now({ post_file: post_file }, should_raise: /will retry later/)
    perform_now({ post_file: post_file }, should_raise: /will retry later/)
    perform_now({ post_file: post_file })
    post_file.reload
    expect(post_file.state).to eq("terminal_error")
    expect(post_file.log_entry).to eq(mock_log_entries[2])
    expect(post_file.last_status_code).to eq(500)
    expect(post_file.retry_count).to eq(3)
  end
end
