# typed: false
require "rails_helper"

describe Scraper::InkbunnyHttpClientConfig do
  subject { described_class.new }

  let!(:username_model) do
    create(
      :global_state,
      key: "inkbunny-username",
      value: "the-user",
      value_type: :string,
    )
  end
  let!(:password_model) do
    create(
      :global_state,
      key: "inkbunny-password",
      value: "the-password",
      value_type: :password,
    )
  end
  let(:performer) do
    SpecUtil.mock_http_performer(
      :post,
      "https://inkbunny.net/api_login.php?username=the-user&password=the-password",
      response_headers: {
        "content-type" => "application/json",
      },
      response_body: '{"sid": "the-sid"}',
    )
  end

  describe "#do_login" do
    context "sid not stored" do
      it "logs in the user and stores sid" do
        expect(GlobalState.find_by(key: "inkbunny-sid")).to be_nil
        subject.do_login(performer)
        sid = GlobalState.find_by(key: "inkbunny-sid")
        expect(sid.value).to eq("the-sid")
      end
    end

    context "sid stored" do
      it "does not log in the user" do
        create(:global_state, key: "inkbunny-sid", value: "the-sid")
        subject.do_login(performer)
        expect(performer).to_not have_received(:do_request)
      end
    end
  end

  describe "#map_uri" do
    let(:sid) { "test_sid_123" }

    before do
      create(
        :global_state,
        key: "inkbunny-sid",
        value: sid,
        value_type: :string,
      )
      subject.do_login(instance_double("Scraper::CurlHttpPerformer"))
    end

    context "when mapping an inkbunny.net URI" do
      it "adds the sid parameter to the query string" do
        uri =
          Addressable::URI.parse(
            "https://inkbunny.net/api_search.php?text=test",
          )
        mapped_uri = subject.map_uri(uri)

        expect(mapped_uri.query_values).to include("sid" => sid)
        expect(mapped_uri.query_values["text"]).to eq("test")
      end

      it "adds sid parameter when no query string exists" do
        uri = Addressable::URI.parse("https://inkbunny.net/api_search.php")
        mapped_uri = subject.map_uri(uri)

        expect(mapped_uri.query_values).to eq("sid" => sid)
      end

      it "preserves commas in query parameters" do
        uri =
          Addressable::URI.parse(
            "https://inkbunny.net/api_search.php?keywords=tag1,tag2",
          )
        mapped_uri = subject.map_uri(uri)

        expect(mapped_uri.query).to include("keywords=tag1,tag2")
        expect(mapped_uri.query).to include("sid=#{sid}")
      end
    end

    context "when mapping a metapix URI" do
      it "does not modify URIs from tx.ib.metapix.net" do
        uri =
          Addressable::URI.parse(
            "https://tx.ib.metapix.net/files/full/123456.jpg",
          )
        mapped_uri = subject.map_uri(uri)

        expect(mapped_uri).to eq(uri)
      end
    end

    context "when sid is not set" do
      before { subject.instance_variable_set(:@sid, nil) }

      it "raises an error" do
        uri = Addressable::URI.parse("https://inkbunny.net/api_search.php")
        expect { subject.map_uri(uri) }.to raise_error("no sid")
      end
    end
  end

  describe "#scrub_stored_uri" do
    it "scrubs username and password" do
      uri =
        subject.scrub_stored_uri(
          Addressable::URI.parse(
            "https://inkbunny.net/api_login.php?username=foo&password=bar",
          ),
        )
      expect(uri).to eq(
        Addressable::URI.parse(
          "https://inkbunny.net/api_login.php?username=*****&password=*****",
        ),
      )
    end
  end
end
