#!/usr/bin/env ruby

require "bundler/inline"
gemfile do
  source "https://rubygems.org"
  gem "multi_repo", require: "multi_repo/cli", path: File.expand_path("..", __dir__)
end

opts = Optimist.options do
  synopsis "Merge a set of pull requests, also setting assignee and labels."

  opt :prs,      "The list of PRs to merge",           :type => :strings, :required => true
  opt :assignee, "GitHub user to assign when merging", :type => :string,  :required => true
  opt :labels,   "Labels to apply when merging",       :type => :strings

  MultiRepo::CLI.common_options(self)
end

# TODO: Normalize any PR format to `org/repo#pr`
PR_REGEX = %r{^([^/#]+/[^/#]+)#([^/#]+)$}
Optimist.die :prs, "must be in the form `org/repo#pr`" unless opts[:prs].all? { |pr| pr.match?(PR_REGEX) }

def merge_pull_request(repo_name, pr_number, dry_run:, **_)
  if dry_run
    puts "** dry-run: github.merge_pull_request(#{repo_name.inspect}, #{pr_number.inspect})".light_black
  else
    begin
      MultiRepo::Service::Github.client.merge_pull_request(repo_name, pr_number)
    rescue Octokit::MethodNotAllowed => err
      raise unless err.to_s.include?("Pull Request is not mergeable")

      puts "** WARN: Pull Request is not mergeable"
    end
  end
end

def add_labels(repo_name, pr_number, labels:, dry_run:, **_)
  labels = Array(labels)
  if dry_run
    puts "** dry-run: github.add_labels_to_an_issue(#{repo_name.inspect}, #{pr_number.inspect}, #{labels.inspect})".light_black
  else
    MultiRepo::Service::Github.client.add_labels_to_an_issue(repo_name, pr_number, labels)
  end
end

def assign_user(repo_name, pr_number, assignee:, dry_run:, **_)
  assignee = assignee[1..] if assignee.start_with?("@")
  if dry_run
    puts "** dry-run: github.update_issue(#{repo_name.inspect}, #{pr_number.inspect}, \"assignee\" => #{assignee.inspect})".light_black
  else
    MultiRepo::Service::Github.client.update_issue(repo_name, pr_number, "assignee" => assignee)
  end
end

opts[:prs].each do |pr|
  puts MultiRepo::CLI.header(pr)

  repo_name, pr_number = PR_REGEX.match(pr).captures

  merge_pull_request(repo_name, pr_number, opts)
  add_labels(repo_name, pr_number, opts) if opts[:labels].present?
  assign_user(repo_name, pr_number, opts)

  puts
end