#!/bin/bash

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0

SECONDS=0

declare -i rc=0
declare -i tests=0
declare -i failures=0
declare -i errors=0
declare -a testsuites

function passed() {
    local message=$1
    echo "  ✅ PASS: $message"
    tests=$tests+1
}

function failed() {
    local message=$1
    echo "  ❌ FAIL: $message"
    tests=$tests+1
    failures=$failures+1
    rc=1
}

function errored() {
    local message=$1
    echo "  ❌ ERROR: $message"
    tests=$tests+1
    errors=$errors+1
    rc=1
}

# https://github.com/testmoapp/junitxml
declare -r JUNITREPORT='junitreport.xml'

declare -r TESTSUITE='  <testsuite name="%s" tests="%s" failures="%s" errors="%s">
%s
  </testsuite>'

declare -r TESTCASE='    <testcase name="%s" />'

declare -r ERRORCASE='    <testcase name="%s">
      <error type="validate" >
<![CDATA[
%s
]]>
      </error>
    </testcase>'

declare -r FAILURECASE='    <testcase name="%s">
      <failure message="unexpected %s" />
    </testcase>'

function buildpolicies() {
    local policies=$1
    local schema=$2
    local -i ltests=0
    local -i lerrors=0
    local testsuite=""

    echo " Running validation on ${policies} and ${schema}"

    echo "// "$policies" generated by cedartest.sh" > $policies
    regex="\.\.\/(.*)\.cedar"
    for file in ../*.cedar
    do
        res=$(cedar validate -f plain --policies $file --schema $schema)
        if [[ $? == 0 ]]
        then
            echo -e "// file: "$file"" >> $policies
            if [[ $file =~ $regex ]]
            then
                name="${BASH_REMATCH[1]}"
                echo -e "@id(\""$name"\")" >> $policies
            fi
            cat $file >> $policies
            echo -e "\n" >> $policies

            passed "validate $file"
            testsuite+=$(printf "$TESTCASE\n" "validate ${file:3}")$'\n'
        else
            errored "validate $file: $res"
            lerrors=$lerrors+1
            testsuite+=$(printf "$ERRORCASE\n" "validate ${file:3}" "$res")$'\n'
        fi
        ltests=$ltests+1
    done
    testsuites+=$(printf "$TESTSUITE\n" "validate" "$ltests" "0" "$lerrors" "${testsuite%?}")$'\n'
}

function authorize() {
    local folder=$1
    local policies=$2
    local -i ltests=0
    local -i lfailures=0
    local testsuite=""
    echo " Running tests in \"${folder}\""
    for decision in ALLOW DENY
    do
        for file in "$folder"/$decision/*.json
        do
            IFS=$'\n' read -r -d '' -a tmp_array < <(cedar authorize -f plain --policies $policies --entities cedarentities.json --request-json "$file" --template-linked ../cedartemplatelinks.json -v && printf $'\n')
            res="${tmp_array[0]}"
            # everything after "note: " line are determining policies
            for i in "${!tmp_array[@]}"; 
            do
                line="${tmp_array[i]}"
                unset tmp_array[i]
                if [[ $line =~ ^note.* ]]
                then
                    break
                fi
            done
            policyIds="$(IFS=\;; echo "${tmp_array[*]}")"
            jsonfile="$(echo "$file" | cut -d '/' -f 3 | cut -d '.' -f 1)"
            if [ "$res" != "$decision" ]
            then
                failed "decision \"${res}\" (expected \"${decision}\") for ${jsonfile} determined by policy id(s):${policyIds}"
                lfailures=$lfailures+1
                testsuite+=$(printf "$FAILURECASE\n" "$decision $jsonfile" "$res")$'\n'
            else
                passed "decision \"${decision}\" for ${jsonfile} determined by policy id(s):${policyIds}"
                testsuite+=$(printf "$TESTCASE\n" "$decision $jsonfile")$'\n'
            fi
            ltests=$ltests+1
        done
    done
    testsuites+=$(printf "$TESTSUITE\n" "$folder" "$ltests" "$lfailures" "0" "${testsuite%?}")$'\n'
}

function junitreport() {
    echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > "$JUNITREPORT"
    echo "<testsuites tests=\"${tests}\" failures=\"${failures}\" errors=\"${errors}\" time=\"${SECONDS}\">" >> "$JUNITREPORT"
    echo "${testsuites%?}" >> "$JUNITREPORT"
    echo "</testsuites>" >> "$JUNITREPORT"
}

echo "Using $(cedar --version)"

# PhotoApp
echo -e "\nTesting PhotoApp..."
buildpolicies "temppolicies.cedar" "../cedarschema.json"

# loop over "testsuite" folders
for folder in */
do
    authorize "${folder%/}" "temppolicies.cedar"
done

# generate test report
junitreport

exit $rc