#!/bin/bash

# First some definitions and functions

: "${ICINGABOT_TOKEN:=}"
: "${PULL_REQUEST_NO:=}"

RE_IS_CONFLICTING="^UU (.*)"
RE_IS_SOURCE_CATALOG="^UU src/([a-z]{2}_[A-Z]{2})/LC_MESSAGES/icinga.po"

PR_QUERY=$(sed ':a;N;$!ba;s/\n/\\n/g' << GRAPHQL
query (\$number: Int!) {
  repository(owner:\"Icinga\", name:\"L10n\") {
    pullRequest(number: \$number) {
      id
      author {
        login
      }
      mergeable
      maintainerCanModify
      headRefName
      headRepository {
        nameWithOwner
        sshUrl
      }
      comments(first: 100) {
        totalCount
        edges {
          node {
            author {
              login
            }
          }
        }
      }
    }
  }
}
GRAPHQL
)
get_pull_request() {
  local pull_request_no="$1"
  local data="{\"query\": \"$PR_QUERY\", \"variables\": {\"number\": $pull_request_no}}"

  curl -sH "Authorization: bearer $ICINGABOT_TOKEN" -d "$data" https://api.github.com/graphql
}

FRIENDLY_REMINDER=$(sed ':a;N;$!ba;s/\n/\\n/g' << TEXT
I would have loved to assist you with your source catalog conflicts!

Though, you've disabled edits for maintainers of Icinga/L10n. :unamused:
As long as you don't enable edits for us you will have to solve conflicts manually.
TEXT
)
FRIENDLY_REMINDER_MUTATION=$(sed ':a;N;$!ba;s/\n/\\n/g' << GRAPHQL
mutation {
  addComment(input: {subjectId: \"<PR_ID>\", body: \"$FRIENDLY_REMINDER\"}) {
    clientMutationId
  }
}
GRAPHQL
)
send_friendly_reminder() {
  local pull_request_id="$1"

  local mutation=$(echo $FRIENDLY_REMINDER_MUTATION | sed "s/<PR_ID>/$pull_request_id/")
  local _=$(
    curl -sH "Authorization: bearer $ICINGABOT_TOKEN" -d "{\"query\": \"$mutation\"}" https://api.github.com/graphql
  )
}

SUCCESS_MESSAGE=$(sed ':a;N;$!ba;s/\n/\\n/g' << TEXT
I successfully solved the conflicts in your source catalog files! :partying_face:

Please make sure to pull my changes before you'll continue with the translation.
Otherwise you'll risk getting conflicts in your working tree with which I can't help you.
TEXT
)
SUCCESS_MESSAGE_MUTATION=$(sed ':a;N;$!ba;s/\n/\\n/g' << GRAPHQL
mutation {
  addComment(input: {subjectId: \"<PR_ID>\", body: \"$SUCCESS_MESSAGE\"}) {
    clientMutationId
  }
}
GRAPHQL
)
send_success_message() {
  local pull_request_id="$1"

  local mutation=$(echo $SUCCESS_MESSAGE_MUTATION | sed "s/<PR_ID>/$pull_request_id/")
  local _=$(
    curl -sH "Authorization: bearer $ICINGABOT_TOKEN" -d "{\"query\": \"$mutation\"}" https://api.github.com/graphql
  )
}

read_json_var() {
  local json="$1"
  local varpath="$2"

  echo $json | jq -r $varpath
}
read_json_blob() {
  local json="$1"
  local varpath="$2"

  echo $json | jq $varpath
}

# Actual script starts here

set -e

manage_remote=true
if [ -n "$PULL_REQUEST_NO" ]; then
  if [ -z "$ICINGABOT_TOKEN" ]; then
    echo "Environment variable ICINGABOT_TOKEN not set"
    exit 1
  fi

  PR_NUMBER="$PULL_REQUEST_NO"
  PR_DATA="$(get_pull_request $PR_NUMBER)"
  PULL_REQUEST=$(read_json_blob "$PR_DATA" .data.repository.pullRequest)

  PR_MERGEABLE=$(read_json_var "$PULL_REQUEST" .mergeable)
  if [[ "$PR_MERGEABLE" != "CONFLICTING" ]] && [[ "$PR_MERGEABLE" != "UNKNOWN" ]]; then
    echo "Ignoring pull request #$PR_NUMBER. No conflicts detected"
    exit
  fi

  echo "Attempting to resolve pull request #$PR_NUMBER..."

  PR_ID=$(read_json_var "$PULL_REQUEST" .id)
  PR_REPO_NAME=$(read_json_var "$PULL_REQUEST" .headRepository.nameWithOwner)

  # If the author disabled maintainer edits, tell him this once
  PR_IS_ACCESSIBLE=$(read_json_var "$PULL_REQUEST" .maintainerCanModify)
  if [[ "$PR_REPO_NAME" != "Icinga/L10n" && "$PR_IS_ACCESSIBLE" == "false" ]]; then
    ICINGABOT_COMMENTED=false

    TOTAL_COMMENTS=$(read_json_var "$PULL_REQUEST" .comments.totalCount)
    for (( i = 0; i < $TOTAL_COMMENTS; i++ )); do
      COMMENT_AUTHOR=$(read_json_var "$PULL_REQUEST" .comments.edges[$i].node.author.login)
      if [[ $COMMENT_AUTHOR != "icingabot" ]]; then
        continue
      fi

      ICINGABOT_COMMENTED=true
      break
    done

    if [ "$ICINGABOT_COMMENTED" == false ]; then
      send_friendly_reminder "$PR_ID"
    fi

    echo "Ignoring pull request #$PR_NUMBER. Maintainer edits are disallowed"
    exit
  fi

  PR_AUTHOR=$(read_json_var "$PULL_REQUEST" .author.login)
  PR_BRANCH=$(read_json_var "$PULL_REQUEST" .headRefName)
  PR_REPO=$(read_json_var "$PULL_REQUEST" .headRepository.sshUrl)

  echo "Resolving pull request #$PR_NUMBER (Author: $PR_AUTHOR, Branch: $PR_BRANCH, Repo: $PR_REPO)"
else
  echo "Attempting to resolve source catalog conflicts in local HEAD"
  manage_remote=false
fi

if [ "$manage_remote" == true ]; then
  # Fetch the remote branch
  git remote add $PR_AUTHOR $PR_REPO
  git fetch $PR_AUTHOR $PR_BRANCH

  # Checkout the branch
  git checkout -b pull/$PR_NUMBER $PR_AUTHOR/$PR_BRANCH
fi

# Attempt to merge main, should fail
git merge --no-ff --no-commit origin/main || true

if [ ! -f .git/MERGE_HEAD ]; then
  echo "Merge aborted or succeeded for some unknown reason. Cancelling pull request resolution"
  exit
fi

# Resolve source catalog conflicts
GIT_STATUS=$(git status -suno)
while IFS= read -r line; do
  if [[ "$line" =~ $RE_IS_CONFLICTING ]] && [[ ${BASH_REMATCH[0]} ]]; then
    # Only a conflict, yet
    FILENAME="${BASH_REMATCH[1]}"

    # Reset file to the author's version
    git checkout --ours $FILENAME

    if [[ "$line" =~ $RE_IS_SOURCE_CATALOG ]] && [[ ${BASH_REMATCH[0]} ]]; then
      # It's a source catalog! Utilize msgmerge to update the source catalog with the latest messages
      LOCALE="${BASH_REMATCH[1]}"
      echo "Resolving file '$FILENAME':"
      msgmerge --update --backup=none --lang=$LOCALE --sort-by-file $FILENAME src/icinga.pot
      git add $FILENAME
    else
      # It's some other file we don't care about. That's the authors duty to fix this
      git add $FILENAME
    fi
  fi
done <<< "$GIT_STATUS"

# Finish the merge
echo -e "Update with base 'origin/main'\n\nResolves source catalog conflicts" > .git/MERGE_MSG
GIT_EDITOR=true git merge --continue

if [ "$manage_remote" == true ]; then
  echo "Successfully resolved pull request #$PR_NUMBER. Pushing the changes now"

  # Push the new changes
  git push $PR_AUTHOR pull/$PR_NUMBER:$PR_BRANCH
  send_success_message "$PR_ID"
else
  echo "Successfully resolved source catalog conflicts in local HEAD"
fi