#!/usr/bin/env bash

# TODO: publish comment with errors to a separate dedicated issue on GitHub,
# if Github Actions fails

source tools/helpers.sh

set -e

# @TODO CI:
# CI_PULL_REQUEST: ${{ github.event.pull_request.number }}
if [ -z "$CI_PULL_REQUEST" ]; then
    echo "\$CI_PULL_REQUEST is empty. Do nothing"
    exit 0
fi

if [ "$CI_PULL_REQUEST" = "false" ]; then
    echo "Not a pull request. Do nothing"
    exit 0
fi

if [ -z "$COMMENTER_GITHUB_TOKEN" ]; then
    echo "\$COMMENTER_GITHUB_TOKEN is empty. Do nothing"
    exit 0
fi

# COMMENTER_GITHUB_USER is nickname of a special github user.
# COMMENTER_GITHUB_TOKEN is token with scope public repo.
# Token can be obtained here https://github.com/settings/tokens/new
# Don't use ANY REAL user as a commenter, because GitHub access scopes are too wide.
echo "Used vars (you can use them to debug locally):"
echo "export COMMENTER_GITHUB_TOKEN=fillme"
echo "export COMMENTER_GITHUB_USER=$COMMENTER_GITHUB_USER"
echo "export PRESET=$PRESET"
echo "export GITHUB_SHA=$GITHUB_SHA"
echo "export GITHUB_RUN_ID=$GITHUB_RUN_ID"
echo "export GITHUB_JOB=$GITHUB_JOB"
echo "export GITHUB_REPOSITORY=$GITHUB_REPOSITORY"
# @TODO CI:
# CI_OTP_RELEASE: ${{ matrix.otp }}
echo "export CI_OTP_RELEASE=$CI_OTP_RELEASE"
echo "export CI_PULL_REQUEST=$CI_PULL_REQUEST"

# IF we only run small tests, the file is missing
touch /tmp/ct_markdown

PRESET="${PRESET:-default}"
CI_OTP_RELEASE="${CI_OTP_RELEASE:-unknown}"

function remove_ct_log_links
{
    mv /tmp/ct_markdown /tmp/ct_markdown_original
    # grep fails if nothing matches
    { grep -v "Report log" /tmp/ct_markdown_original || echo ""; } > /tmp/ct_markdown
}

# https://stackoverflow.com/questions/407523/escape-a-string-for-a-sed-replace-pattern
function replace_string {
    sed -i "s/$( \
        echo "$1" | sed -e 's/\([[\/.*]\|\]\)/\\&/g' \
                  | sed -e 's:\t:\\t:g' \
    )/$( \
        echo "$2" | sed -e 's/[\/&]/\\&/g' \
                  | sed -e 's:\t:\\t:g' \
    )/g" "$3"
}

function rewrite_log_links_to_s3
{
    local CT_REPORT=big_tests/ct_report
    local CT_REPORT_ABS=$(./tools/abs_dirpath.sh "$CT_REPORT")
    local CT_REPORTS=$(ct_reports_dir)
    local BIG_TESTS_URL="$(archive_reader_url big ${CT_REPORTS})"
    cp /tmp/ct_markdown /tmp/ct_markdown_original
    replace_string "$CT_REPORT_ABS" "$BIG_TESTS_URL" /tmp/ct_markdown
    # URL escape for s3_reports.html script
    replace_string "ct_run.test@" "ct_run.test%40" /tmp/ct_markdown
}

function last_ct_run_name
{
    ls -1 -t big_tests/ct_report/ | grep ct_run | head -n1
}


function small_suite_path
{
    if [ -d _build/test/logs ]; then
        cd _build/test/logs
        ls -t -1 ct_run.mongooseim@localhost.*/lib.mongooseim.logs/run.*/suite.log.html
        cd ../../..
    fi
}

function ct_run_url
{
    local CT_REPORTS=$(ct_reports_dir)
    local BIG_TESTS_URL="$(archive_reader_url big ${CT_REPORTS})"
    local RUN_PART=$(echo "$(last_ct_run_name)" | sed "s/@/%40/g")
    echo "$BIG_TESTS_URL/$RUN_PART/index.html"
}

function ct_small_url
{
    local CT_REPORTS=$(ct_reports_dir)
    local SMALL_TESTS_URL="$(archive_reader_url small ${CT_REPORTS})"
    local SUFFIX=$(small_suite_path)
    echo "$SMALL_TESTS_URL/$SUFFIX"
}

function reports_url
{
    local CT_REPORTS=$(ct_reports_dir)
    s3_url "${CT_REPORTS}"
}

if [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
    REPORTS_URL_BODY="Reports are not uploaded"$'\n'
    remove_ct_log_links
else
    REPORTS_URL="$(reports_url)"
    CT_RUN_URL="$(ct_run_url)"
    SMALL_CT_URL="$(ct_small_url)"
    REPORTS_BIG_URL_BODY=""
    REPORTS_SMALL_URL_BODY=""
    if [ -d big_tests/ct_report ]; then
        rewrite_log_links_to_s3
        REPORTS_BIG_URL_BODY="/ [big]($CT_RUN_URL)"
    fi
    if [ -d _build/test/logs ]; then
        REPORTS_SMALL_URL_BODY=" / [small]($SMALL_CT_URL)"
    fi
    REPORTS_URL_BODY="Reports [root](${REPORTS_URL})${REPORTS_BIG_URL_BODY}${REPORTS_SMALL_URL_BODY}"$'\n'
fi

COUNTERS_FILE=/tmp/ct_stats_vars
COUNTERS_BODY=""
if [ -f "$COUNTERS_FILE" ]; then
    . "$COUNTERS_FILE"
    COUNTERS_BODY="**OK: $CT_COUNTER_OK** "
    if [ "$CT_COUNTER_FAILED" != "0" ]; then
        COUNTERS_BODY="$COUNTERS_BODY/ **Failed: $CT_COUNTER_FAILED** "
    else
        COUNTERS_BODY="$COUNTERS_BODY/ Failed: 0 "
    fi
    if [ "$CT_COUNTER_USER_SKIPPED" != "0" ]; then
        COUNTERS_BODY="$COUNTERS_BODY/ **User-skipped: $CT_COUNTER_USER_SKIPPED** "
    else
        COUNTERS_BODY="$COUNTERS_BODY/ User-skipped: 0 "
    fi
    if [ "$CT_COUNTER_AUTO_SKIPPED" != "0" ]; then
        COUNTERS_BODY="$COUNTERS_BODY/ **Auto-skipped: $CT_COUNTER_AUTO_SKIPPED** "
    else
        COUNTERS_BODY="$COUNTERS_BODY/ Auto-skipped: 0 "
    fi
    COUNTERS_BODY="$COUNTERS_BODY"$'\n'
fi

TRUNCATED_BODY=""
# Number of truncated failed tests if file exists
TRUNCATED_FILE="/tmp/ct_markdown_truncated"
if [ -f "$TRUNCATED_FILE" ]; then
    TRUNCATED_COUNTER=$(cat "$TRUNCATED_FILE")
    TRUNCATED_BODY=$'\n'$'\n'"$TRUNCATED_COUNTER errors were truncated"
fi

# Link to a GitHub Actions job
JOB_URL="https://github.com/esl/MongooseIM/actions/runs/$GITHUB_RUN_ID"
DESC_BODY="[$GITHUB_JOB]($JOB_URL) / Erlang $CI_OTP_RELEASE / $PRESET / $GITHUB_SHA"$'\n'
# This file is created by ct_markdown_errors_hook
ERRORS_BODY="$(cat /tmp/ct_markdown || echo '/tmp/ct_markdown missing')"
BODY="${DESC_BODY}${REPORTS_URL_BODY}${COUNTERS_BODY}${ERRORS_BODY}${TRUNCATED_BODY}"
# SLUG is the same for both GitHub and GitHub Actions CI
GITHUB_REPOSITORY=${GITHUB_REPOSITORY:-esl/MongooseIM}

function post_new_comment
{
# Create a comment GitHub API doc
# https://developer.github.com/v3/issues/comments/#create-a-comment
echo "Posting a new comment"
POST_BODY=$(BODY_ENV="$BODY" jq -n '{body: env.BODY_ENV}')
curl -o /dev/null -i \
    -H "Authorization: token $COMMENTER_GITHUB_TOKEN" \
    -H "Content-Type: application/json" \
    -X POST -d "$POST_BODY" \
    https://api.github.com/repos/$GITHUB_REPOSITORY/issues/$CI_PULL_REQUEST/comments
}

function append_comment
{
# Concat old comment text and some extra text
# Keep a line separator between them
# $'\n' is a new line in bash
#
# Edit commment GitHub API doc
# https://developer.github.com/v3/issues/comments/#edit-a-comment
COMMENT_ID="$1"
echo "Patch comment $COMMENT_ID"
BODY_FROM_GH="$(cat /tmp/gh_comment | jq -r .body)"
BODY="${BODY_FROM_GH}"$'\n'$'\n'"---"$'\n'$'\n'"${BODY}"
PATCH_BODY=$(BODY_ENV="${BODY}" jq -n '{body: env.BODY_ENV}')
curl -o /dev/null -i \
    -H "Authorization: token $COMMENTER_GITHUB_TOKEN" \
    -H "Content-Type: application/json" \
    -X PATCH -d "$PATCH_BODY" \
    https://api.github.com/repos/$GITHUB_REPOSITORY/issues/comments/$COMMENT_ID
}

# List comments
# https://developer.github.com/v3/issues/comments/#list-comments-on-an-issue
curl -s -S -o /tmp/gh_comments -L \
    -H "Authorization: token $COMMENTER_GITHUB_TOKEN" \
    -H "Content-Type: application/json" \
    https://api.github.com/repos/$GITHUB_REPOSITORY/issues/$CI_PULL_REQUEST/comments

# Filter out all comments for a particular user
# Then filter out all comments that have a git commit rev in the body text
# Then take first comment (we don't expect more comments anyway)
cat /tmp/gh_comments | jq "map(select(.user.login == \"$COMMENTER_GITHUB_USER\")) | map(select(.body | contains(\"$GITHUB_SHA\")))[0]" > /tmp/gh_comment
COMMENT_ID=$(cat /tmp/gh_comment | jq .id)

if [ "$COMMENT_ID" = "null" ]; then
    post_new_comment
else
    append_comment "$COMMENT_ID"
fi
