#!/usr/bin/python3
# SPDX-License-Identifier: Apache-2.0

import enarxbot
import random

QUERY = """
query($user:String!) {
  user(login:$user) {
    status {
      indicatesLimitedAvailability
    }
  }
}
"""

# Moves random users from src to dst until src is exhausted or dst has max users.
#
# Randomly selected users who have set their GitHub status to `busy` are removed
# from src but are not added to dst.
def migrate(dst, src, max=None):
    while len(src) > 0 and (max is None or len(dst) < max):
        one = random.sample(src, 1)[0]
        src.remove(one)

        status = enarxbot.graphql(QUERY, user=one)["user"]["status"]
        if status is None or not status["indicatesLimitedAvailability"]:
            dst.add(one)

github = enarxbot.connect()
org = github.get_organization("enarx")
reviews = {t.name: t for t in org.get_teams()}['reviews']
potential_reviewers = {r.login for r in reviews.get_members()}

# Auto-assign for all PRs in the org.
for issue in github.search_issues(f"org:enarx is:pr is:public is:open -is:draft"):
    repo = issue.repository
    pr = issue.as_pull_request()
    suggestions = enarxbot.Suggestion.query(github, repo, pr)

    # All currently requested reviewers.
    requested = {r.user.login for r in pr.get_reviews()}
    requested |= {r.login for r in pr.get_review_requests()[0]}

    # Get our categories.
    reviewers = potential_reviewers.copy()
    suggested = {s.reviewer.login for s in suggestions}
    authors = {pr.user.login}
    owners = {"npmccallum"}

    # Make sure categories are mutually exclusive.
    reviewers -= authors | owners | suggested
    suggested -= authors | owners
    owners -= authors

    requesting = requested.copy()     # Existing reviewers
    migrate(requesting, owners)       # Get all owners.
    migrate(requesting, suggested, 2) # Get some suggested, leave room for non-suggested.
    migrate(requesting, reviewers, 3) # Get some non-suggested.
    migrate(requesting, suggested, 3) # Backfill from suggested.

    # Print status.
    print(f"{repo.name}#{pr.number}:", end="")
    for user in sorted(requesting):
        state = "" if user in requested else "+"
        print(f" {state}{user}", end="")
    print()

    # With all three selected, request them as reviewers.
    enarxbot.review_request(pr, reviewers=list(requesting - requested))
