#!/bin/bash

# This script executes the tests and starts the database docker container if necessary.

# Import utility functions
# shellcheck source=./tools/_functions.sh
source "$(dirname "${BASH_SOURCE[0]}")/_functions.sh"

# Delete outdated code coverage report
CODE_COVERAGE_DIR="${BASE_DIR:?}/htmlcov"
rm -rf "${CODE_COVERAGE_DIR}"

require_installed

ensure_webpack_bundle_exists

require_database

# Set dummy key to enable SUMM.AI during testing
export INTEGREAT_CMS_SUMM_AI_API_KEY="dummy"

# Set dummy key to enable DeepL during testing
export INTEGREAT_CMS_DEEPL_AUTH_KEY="dummy"

# Set dummy key to enable Textlab during testing
export INTEGREAT_CMS_TEXTLAB_API_KEY="dummy"
# Set Google credentials and project ID to enable Google Translate during testing
export INTEGREAT_CMS_GOOGLE_CREDENTIALS="dummy.json"
export INTEGREAT_CMS_GOOGLE_PROJECT_ID="dummy"

# Disable linkcheck listeners during testing
export INTEGREAT_CMS_LINKCHECK_DISABLE_LISTENERS=1

# Disable background tasks during testing
export INTEGREAT_CMS_BACKGROUND_TASKS_ENABLED=0

TESTS=()

# Parse given command line arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        # If only tests affected by recent changed should be run, --changed can be passed as a flag
        --changed) CHANGED=1;shift;;
        # Verbosity for pytest
        -v|-vv|-vvv|-vvvv) VERBOSITY="$1";shift;;
        # Select tests by keyword expression
        -k) shift;KW_EXPR="$1";shift;;
        # Select tests by marker
        -m) shift;MARKER="$1";shift;;
        # If only particular tests should be run, test path can be passed as CLI argument
        *) TESTS+=("$1");shift;;
    esac
done

# The default pytests args we use
PYTEST_ARGS=("--disable-warnings" "--color=yes")

if [[ -n "${VERBOSITY}" ]]; then
    PYTEST_ARGS+=("$VERBOSITY")
else
    PYTEST_ARGS+=("--quiet" "--numprocesses=auto")
fi

# Check if --changed flag was passed
if [[ -n "${CHANGED}" ]]; then
    # Check if .testmondata file exists
    if [[ -f ".testmondata" ]]; then
        # Only run changed tests and don't update dependency database
        PYTEST_ARGS+=("--testmon-nocollect")
        CHANGED_MESSAGE=" affected by recent changes"
    else
        # Inform that all tests will be run
        echo -e "\nIt looks like you have not run pytest without the \"--changed\" flag before." | print_warning
        echo -e "Pytest has to build a dependency database by running all tests without the flag once.\n" | print_warning
        # Override test path argument
        unset TESTS
        # Tell testmon to run all tests and collect data
        PYTEST_ARGS+=("--testmon-noselect")
    fi
else
    # Run all tests, but update list of tests
    PYTEST_ARGS+=("--testmon-noselect")
fi

# Determine whether coverage data should be collected
if [[ -z "${CHANGED}" ]] && (( ${#TESTS[@]} == 0 )); then
    PYTEST_ARGS+=("--cov=integreat_cms" "--cov-report=html")
fi

if [[ -n "${KW_EXPR}" ]] || [[ -n "${MARKER}" ]] || (( ${#TESTS[@]} )); then
    TEST_MESSAGE=""
    if [[ -n "${KW_EXPR}" ]]; then
        TEST_MESSAGE+=" \"${KW_EXPR}\""
        PYTEST_ARGS+=("-k" "${KW_EXPR}")
    fi
    if [[ -n "${MARKER}" ]]; then
        TEST_MESSAGE+=" with ${MARKER}"
        PYTEST_ARGS+=("-m" "${MARKER}")
    fi
    FILES=()
    # Check whether test paths exist
    for t in "${TESTS[@]}"; do
        if [[ -e "${t%%::*}" ]]; then
            # Adapt message and append to pytest arguments
            FILES+=("${t}")
            PYTEST_ARGS+=("${t}")
        elif [[ -n "${t}" ]]; then
            # If the test path does not exist but was non-zero, show an error
            echo -e "${t%%::*}: No such file or directory" | print_error
            exit 1
        fi
    done
    FILES_MESSAGE=$(join_by ", " "${FILES[@]}")
    TEST_MESSAGE+=" in $FILES_MESSAGE"
fi

"$(dirname "${BASH_SOURCE[0]}")/prune_pdf_cache.sh"

echo -e "Running all tests${TEST_MESSAGE}${CHANGED_MESSAGE}..." | print_info
deescalate_privileges pytest "${PYTEST_ARGS[@]}"
echo "✔ Tests successfully completed " | print_success

if [[ -d "${CODE_COVERAGE_DIR}" ]]; then
    echo -e "Open the following file in your browser to view the test coverage:\n" | print_info
    echo -e "\tfile://${CODE_COVERAGE_DIR}/index.html\n" | print_bold
fi
