#!/usr/bin/bash
#
# Copyright (C) 2024-2026 Red Hat, Inc.
#
# 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.

# send status to github and gerrit according to the command line arguments
#
# for github verify that the check is not already on error or failure before updating the status

set -ex

# Check for the required arguments
if [ $# -lt 3 ]; then
    cat <<EOF
Usage: $0 [-f] <DIR> <state> <description> [<DCI job url>]

  -f means do not verify the status of the Github check.
  <DIR> is the top directory where the change is stored.
  <state> can be pending, success, error, failure.
  <description> is the text to display in Github or Gerrit.
EOF
    exit 1
fi

if [ "$1" = "-f" ]; then
    FORCE=1
    shift
else
    FORCE=
fi

DIR="$1"
STATE="$2"
DESCRIPTION="$3"
DCI_URL="$4"

TOPDIR=$(cd $(dirname $0); pwd)

if [[ $0 =~ .*-podman$ ]]; then
    SUFFIX=-podman
else
    SUFFIX=
fi

if [ -r "$TOPDIR/common$SUFFIX" ]; then
    BASEDIR="$TOPDIR"
else
    BASEDIR=/usr/share/dci-pipeline
fi

. "$BASEDIR/common$SUFFIX"

# verify check is in cancelled, failure, success, pending
if ! grep -q -E '^(error|failure|success|pending)$' <<< "$STATE"; then
    echo "Invalid state: $STATE"
    exit 1
fi

# verify directory exists
if [ ! -d "$DIR" ]; then
    echo "Directory $DIR does not exist"
    exit 1
fi

# process all the json files representing the various parts of the change
for json in $(ls $DIR/*.json); do
    # Gerrit
    if [ $(jq -r .url $json) = null ]; then
        if [ -z $GERRIT_SSH_LOGIN ] || [ -z $GERRIT_SSH_ID ]; then
          echo "GERRIT_SSH_LOGIN or GERRIT_SSH_ID are not defined, the review is not updated"
          continue
        fi

        CHANGEID=$(jq -r ._number $json)
        CURREV=$(jq -r .current_revision $json)
        PATCHSET=$(jq -r ".revisions[\"$CURREV\"]._number" $json)
        GERRIT_JSON="{\"message\":\"${BODY}\",\"tag\":\"autogenerated:dci-change\"}"

        case "$STATE" in
            pending)
                VOTE=0
                ;;
            error|failure)
                VOTE=-1
                ;;
            success)
                VOTE=+1
                ;;
            *)
                echo "Invalid state: $STATE"
                exit 1
                ;;
        esac

        GERRIT_JSON=$( echo ${GERRIT_JSON} | jq '. += {"labels": {"verified": "'${VOTE}'"}}' )
        GERRIT_CHANGE_STATUS=$(jq -r .submit_records[0].status $json)

        # Only update changes that are not closed
        if [ "${GERRIT_CHANGE_STATUS}" != "CLOSED" ]; then
            # Use json to allow message to be formatted
            echo "$GERRIT_JSON" |
              ssh \
              -i ~/.ssh/"$GERRIT_SSH_ID" \
              -p 29418 \
              "${GERRIT_SSH_LOGIN}@softwarefactory-project.io" \
                gerrit review -j "$CHANGEID,$PATCHSET"
        fi
    # Github PR or merge queue branch
    else
        REPO_NAME=$(jq -r .head.repo.name $json)

        if ! [[ -n "$GITHUB_VOTING_REPOS" && "$REPO_NAME" =~ $GITHUB_VOTING_REPOS ]]; then
            continue
        fi

        FULL_NAME=$(jq -r .head.repo.full_name $json)
        REPO_TOKEN=$($BASEDIR/get-config-entry "https://github.com/$FULL_NAME" github_token "$GITHUB_TOKEN")
        STATUSES_URL=$(jq -r .statuses_url $json)
        GH_HEADERS=(
          "Accept: application/vnd.github.v3+json"
          "X-GitHub-Api-Version: 2022-11-28"
        )

        if [ -n "$REPO_TOKEN" ]; then
            GH_HEADERS+=("Authorization: token ${REPO_TOKEN}")
        fi

        if [ -z "$FORCE" ]; then
            # get the current status
            CURRENT_STATUS=$(curl -s "${GH_HEADERS[@]/#/-H}" "$STATUSES_URL" | jq -r '.[] | select(.context == "'"$GITHUB_CHECK_NAME"'") | .state'|head -1)

            # skip if the current status is already on error or failure
            if grep -q -E '^(error|failure)$' <<< "$CURRENT_STATUS"; then
                continue
            fi
        fi

        # add the DCI URL if provided
        if [ -n "$DCI_URL" ]; then
            TARGET_URL=",\"target_url\": \"$DCI_URL\""
        else
            TARGET_URL=
        fi

        # send the status
        curl -s "${GH_HEADERS[@]/#/-H}" -X POST -d "{\"state\":\"$STATE\",\"description\":\"$DESCRIPTION\",\"context\":\"$GITHUB_CHECK_NAME\"$TARGET_URL}" "$STATUSES_URL"
    fi

done

# send_status ends here
