#!/usr/bin/env bash
usage() {
    echo "$0 [COMMAND]"
    echo ""
    echo "Hint: All commands expect a Python dev virtual environment to be active"
    echo ""
    echo "  Commands:"
    echo "  - lint                :    run ruff on all packages or on specific directories defining them as input, e.g., bash ./run lint hdhelpers"
    echo "  - test                :    run pytest on all packages or on specific directories defining them as input, e.g., bash ./run test test"
    echo "  - typecheck           :    run mypy static type check"
    echo "  - format              :    run ruff format"
    echo "  - check               :    run format check, tests, typechecking"
    echo "  - build_docs          :    runs sphinx to generate python package documentation"
    echo "  - build_package       :    builds package with defined version"
    echo "  - test-py-versions    :    runs tests on several python version using uv run --python"
}

set -euo pipefail

fn_exists() {
    LC_ALL=C type "${1:-}" 2>/dev/null | grep -q 'function'
}
COMMAND="${1:-}"
shift
ARGUMENTS=("${@}")

#----- subcommands -----#


lint(){
    if (( ${#} == 0 )) ; then
        uv run ruff check src/hdhelpers --exclude "**/__init__.py"
    else
        uv run ruff check "${@}"
    fi
}

build_docs(){
    uv pip install .
    uv run sphinx-build -M html sphinx/source sphinx/build
    uv run sphinx-build -M doctest sphinx/source sphinx/build
    uv run pytest --doctest-modules src/hdhelpers/metadata/_specs.py
    cp -r sphinx/build/html/* docs/
}


format() {
    uv run ruff check --select I src tests --fix "${@}" && echo "--> Ruff import sorting run."
    uv run ruff format src tests "${@}" && echo "--> ruff format run."
}


test() {
    if (( ${#} == 0 )) ; then
        echo "Testing hdhelpers package code ..."
        uv run pytest tests -c pytest.ini \
        --cov=hdhelpers --no-cov-on-fail \
        --ignore=*/__init__.py
        uv run coverage xml -i -o coverage.xml
    else
        uv run pytest "${@}" \
        --cov="${@}" \
        --no-cov-on-fail --cov-report=term-missing:skip-covered
    fi
}


typecheck() {
    uv run mypy "${@}" src
}


check() {
    # Will fail with non-zero exit status if any tool has some complaint.
    # If everything is okay this will have 0 exits status
    local no_tests="false"

     # Parse flags
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --no-tests)
                no_tests="true"
                shift
                ;;
            *)
                echo "Unknown option: $1"
                exit 1
                ;;
        esac
    done

    if [[ "$no_tests" == "true" ]]; then
        echo "--> Running ruff format in check mode" && uv run ruff format src tests --check &&
        echo "--> Running mypy" && uv run mypy src &&
        echo "--> Running ruff" && uv run ruff check src tests &&
        echo "--> Creating docu" && install_editable_package && build_docs &&
        echo "CHECKS EXECUTION RESULTS: All checks were successful!"
    else
        echo "--> Running ruff format in check mode" && uv run ruff format src tests --check &&
        echo "--> Running tests" && uv run pytest tests -c pytest.ini --cov=. --cov-report=term-missing --cov-fail-under=80 &&
        echo "--> Running mypy" && uv run mypy src &&
        echo "--> Running ruff" && uv run ruff check src tests &&
        echo "--> Creating docu" && install_editable_package && build_docs &&
        echo "CHECKS EXECUTION RESULTS: All checks were successful!"
    fi
}

install_editable_package(){
    uv pip install -e .
}

build_package(){
    uv sync --frozen
    rm -f -r dist
    uv version $@
    sed -i "s/^__version__ = .*/__version__ = \"$@\"/" src/hdhelpers/__init__.py
    uv build --no-sources
}

test-py-versions() {
    echo "Py 3.12" && uv run --python=3.12 --all-extras pytest tests -c pytest.ini --cov=. --cov-report=term-missing --cov-fail-under=80 &&
    echo "Py 3.13" && uv run --python=3.13 --all-extras pytest tests -c pytest.ini --cov=. --cov-report=term-missing --cov-fail-under=80 &&
    echo "Py 3.14" && uv run --python=3.14 --all-extras pytest tests -c pytest.ini --cov=. --cov-report=term-missing --cov-fail-under=80
}

#----- Execution -----#
if fn_exists "$COMMAND"; then
    # cd into the script's current directory
    cd "${0%/*}" || exit 1
    # Execute
    TIMEFORMAT=$'\nTask completed in %3lR'
    time "$COMMAND" "${ARGUMENTS[@]}"
else
    usage
fi
