#!/usr/bin/env bash

# Copyright 2022 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Usage: `sync-bug-triage-github-project-beta.sh`
# Pre-requisite: add a GITHUB_TOKEN as the environment variable (Ref: https://github.com/kubernetes/org/issues/3558)

set -eu -o pipefail

: "${ORGANIZATION:=kubernetes}"
: "${REPOSITORY:=kubernetes}"

PROJECT_NUMBER=${PROJECT_NUMBER:-}
MILESTONE=${MILESTONE:-}

if [ "${GITHUB_TOKEN:-}" == "" ]; then
      echo "[Error] Required environment variable \"GITHUB_TOKEN\" is not set."
      exit 1
fi

if [ "$PROJECT_NUMBER" == "" ]; then
      echo "[Error] Required environment variable \"PROJECT_NUMBER\" is not set."
      exit 1
fi

if [ "$MILESTONE" == "" ]; then
      echo "[Error] Required environment variable \"MILESTONE\" is not set."
      exit 1
fi

GITHUB_TOKEN="$(echo "$GITHUB_TOKEN" | tr -d '\n')"

milestone_issue_ids=()
milestone_pr_ids=()


## Function definitions

function get_project_id_from_github_beta_project() {
    query='.data.organization.projectV2.id'

    ID="$( gh api graphql -f query='
                    query($org: String!, $number: Int!) {
                    organization(login: $org){
                        projectV2(number: $number) {
                        id
                        fields(first:100) {
                            nodes {
                            ... on ProjectV2Field {
                                id
                                name
                            }
                            ... on ProjectV2SingleSelectField {
                                id
                                name
                                options {
                                    id
                                    name
                                }
                            }
                            }
                        }
                        }
                    }
                    }' -f org="${ORGANIZATION}" -F number="${PROJECT_NUMBER}" --jq "$query")"
    echo "$ID"
}


echo 'Starting sync...'
echo -e "[INFO] Fetching the list of open issues and PRs from k/k under the current release milestone, ${MILESTONE}"


## Fetch issues
MILESTONE_ISSUES_JSON="$(gh api graphql --paginate -f query='
            query($org: String!, $repo: String!, $milestone: String!, $endCursor: String){
              repository(owner: $org, name: $repo) {
                description
                url
                milestones(states: [OPEN],first:1, query: $milestone) {
                  nodes{
                    issues(states:[OPEN], first: 100, after: $endCursor){
                      nodes{
                        id
                      }
                      pageInfo{
                        hasNextPage
                        endCursor
                      }
                    }
                  }
                }
              }
            }' -f org="${ORGANIZATION}" -f repo="${REPOSITORY}" -f milestone="${MILESTONE}")"

milestone_issues=($(jq ".data.repository.milestones.nodes[].issues.nodes | length" <<< "${MILESTONE_ISSUES_JSON}"))

for issues in "${milestone_issues[@]}"
do
	for index in $(seq 0 $(( issues - 1 )));
	do
		issue_id=($(jq ".data.repository.milestones.nodes[].issues.nodes[$index].id" <<< "${MILESTONE_ISSUES_JSON}"))
		milestone_issue_ids+=("${issue_id[@]}")
	done
done


## Fetch PRs
MILESTONE_PRS_JSON="$(gh api graphql --paginate -f query='
            query($org: String!, $repo: String!, $milestone: String!, $endCursor: String){
              repository(owner: $org, name: $repo) {
                description
                url
                milestones(states: [OPEN],first:1, query: $milestone) {
                  nodes{
                    pullRequests(states:[OPEN], first: 100, after: $endCursor){
                      nodes{
                        id
                      }
                      pageInfo{
                        hasNextPage
                        endCursor
                      }
                    }
                  }
                }
              }
            }' -f org="${ORGANIZATION}" -f repo="${REPOSITORY}" -f milestone="${MILESTONE}")"


milestone_prs=($(jq ".data.repository.milestones.nodes[].pullRequests.nodes | length" <<< "${MILESTONE_PRS_JSON}"))

for prs in "${milestone_prs[@]}"
do
	for index in $(seq 0 $(( prs - 1 )));
	do
		pr_id=($(jq ".data.repository.milestones.nodes[].pullRequests.nodes[$index].id" <<< "${MILESTONE_PRS_JSON}"))
		milestone_pr_ids+=("${pr_id[@]}")
	done
done


## Fetch Project metadata
echo -e "[INFO] Getting metadata for the Bug Triage GitHub Beta Project with ID: ${PROJECT_NUMBER}"

PROJECT_ID=$( get_project_id_from_github_beta_project)


## Add data to the Project Board
echo  '[INFO] Feeding data from k/k issues into the GitHub Project Beta'

for issue_id in "${milestone_issue_ids[@]}";
do
	# Issues
	if  [ "${issue_id}" !=  null ]; then
      		item_id="$( gh api graphql -f query='
            		mutation($project:ID!, $issue:ID!) {
              		addProjectV2ItemById(input: {projectId: $project, contentId: $issue}) {
                		item {
                  			id
               			}
              		}
            	}' -f project="${PROJECT_ID}" -f issue="${issue_id}" --jq '.data.addProjectV2ItemById.item.id')"
	fi
done

echo  '[INFO] Feeding data from k/k PRs into the GitHub Project Beta'

for pr_id in "${milestone_pr_ids[@]}";
do
	# PRs
	if  [ "${pr_id}" !=  null ]; then
		item_id="$( gh api graphql -f query='
			mutation($project:ID!, $pr:ID!) {
              		addProjectV2ItemById(input: {projectId: $project, contentId: $pr}) {
                		item {
                 			 id
               		  	}
              		}
            	}' -f project="${PROJECT_ID}" -f pr="${pr_id}" --jq '.data.addProjectV2ItemById.item.id')"
	fi
done

echo 'Sync finished!'
