# frozen_string_literal: true

require "rails_helper"

RSpec.describe DiscourseAi::AiBot::Tools::GithubSearchCode do
  let(:bot_user) { Fabricate(:user) }
  fab!(:llm_model)
  let(:llm) { DiscourseAi::Completions::Llm.proxy("custom:#{llm_model.id}") }
  let(:tool) { described_class.new({ repo: repo, query: query }, bot_user: bot_user, llm: llm) }

  context "with valid search results" do
    let(:repo) { "discourse/discourse" }
    let(:query) { "def hello" }

    it "searches for code in the repository" do
      stub_request(
        :get,
        "https://api.github.com/search/code?q=def%20hello+repo:discourse/discourse",
      ).with(
        headers: {
          "Accept" => "application/vnd.github.v3.text-match+json",
          "User-Agent" => DiscourseAi::AiBot::USER_AGENT,
        },
      ).to_return(
        status: 200,
        body: {
          total_count: 1,
          items: [
            {
              path: "test/hello.rb",
              name: "hello.rb",
              text_matches: [{ fragment: "def hello\n  puts 'hello'\nend" }],
            },
          ],
        }.to_json,
      )

      result = tool.invoke
      expect(result[:search_results]).to include("def hello\n  puts 'hello'\nend")
      expect(result[:search_results]).to include("test/hello.rb")
      expect(result[:error]).to be_nil
    end
  end

  context "with an empty search result" do
    let(:repo) { "discourse/discourse" }
    let(:query) { "nonexistent_method" }

    describe "#description_args" do
      it "returns the repo and query" do
        expect(tool.description_args).to eq(repo: repo, query: query)
      end
    end

    it "returns an empty result" do
      SiteSetting.ai_bot_github_access_token = "ABC"
      stub_request(
        :get,
        "https://api.github.com/search/code?q=nonexistent_method+repo:discourse/discourse",
      ).with(
        headers: {
          "Accept" => "application/vnd.github.v3.text-match+json",
          "User-Agent" => DiscourseAi::AiBot::USER_AGENT,
          "Authorization" => "Bearer ABC",
        },
      ).to_return(status: 200, body: { total_count: 0, items: [] }.to_json)

      result = tool.invoke
      expect(result[:search_results]).to be_empty
      expect(result[:error]).to be_nil
    end
  end

  context "with an error response" do
    let(:repo) { "discourse/discourse" }
    let(:query) { "def hello" }

    it "returns an error message" do
      stub_request(
        :get,
        "https://api.github.com/search/code?q=def%20hello+repo:discourse/discourse",
      ).with(
        headers: {
          "Accept" => "application/vnd.github.v3.text-match+json",
          "User-Agent" => DiscourseAi::AiBot::USER_AGENT,
        },
      ).to_return(status: 403)

      result = tool.invoke
      expect(result[:search_results]).to be_nil
      expect(result[:error]).to include("Failed to perform code search")
    end
  end
end
