# frozen_string_literal: true

module DiscourseAi
  module AiBot
    module Tools
      class GithubSearchFiles < Tool
        def self.signature
          {
            name: name,
            description:
              "Searches for files in a GitHub repository containing specific keywords in their paths or names",
            parameters: [
              {
                name: "repo",
                description: "The repository name in the format 'owner/repo'",
                type: "string",
                required: true,
              },
              {
                name: "keywords",
                description: "An array of keywords to match in file paths or names",
                type: "array",
                item_type: "string",
                required: true,
              },
              {
                name: "branch",
                description:
                  "The branch or commit SHA to search within (default: repository's default branch)",
                type: "string",
                required: false,
              },
            ],
          }
        end

        def self.name
          "github_search_files"
        end

        def repo
          parameters[:repo]
        end

        def keywords
          parameters[:keywords]
        end

        def branch
          parameters[:branch]
        end

        def description_args
          { repo: repo, keywords: keywords.join(", "), branch: @branch_name }
        end

        def invoke
          # Fetch the default branch if no branch is specified
          branch_name = branch || fetch_default_branch(repo)
          @branch_name = branch_name

          api_url = "https://api.github.com/repos/#{repo}/git/trees/#{branch_name}?recursive=1"

          response_code = "unknown error"
          tree_data = nil

          send_http_request(
            api_url,
            headers: {
              "Accept" => "application/vnd.github.v3+json",
            },
            authenticate_github: true,
          ) do |response|
            response_code = response.code
            if response_code == "200"
              begin
                tree_data = JSON.parse(read_response_body(response))
              rescue JSON::ParserError
                response_code = "500 - JSON parse error"
              end
            end
          end

          if response_code == "200"
            matching_files =
              tree_data["tree"]
                .select do |item|
                  item["type"] == "blob" &&
                    keywords.any? { |keyword| item["path"].include?(keyword) }
                end
                .map { |item| item["path"] }

            { matching_files: matching_files, branch: branch_name }
          else
            { error: "Failed to perform file search. Status code: #{response_code}" }
          end
        end
      end
    end
  end
end
