#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
BACKEND_DIR="$ROOT_DIR/backend"
COVERAGE_FILE="$BACKEND_DIR/coverage.txt"
MIN_COVERAGE="${CHARON_MIN_COVERAGE:-${CPM_MIN_COVERAGE:-85}}"

# Perf asserts are sensitive to -race overhead; loosen defaults for hook runs
export PERF_MAX_MS_GETSTATUS_P95="${PERF_MAX_MS_GETSTATUS_P95:-25ms}"
export PERF_MAX_MS_GETSTATUS_P95_PARALLEL="${PERF_MAX_MS_GETSTATUS_P95_PARALLEL:-50ms}"
export PERF_MAX_MS_LISTDECISIONS_P95="${PERF_MAX_MS_LISTDECISIONS_P95:-75ms}"

# trap 'rm -f "$COVERAGE_FILE"' EXIT

cd "$BACKEND_DIR"

# Packages to exclude from coverage (main packages and infrastructure code)
# These are entrypoints and initialization code that don't benefit from unit tests
EXCLUDE_PACKAGES=(
    "github.com/Wikid82/charon/backend/cmd/api"
    "github.com/Wikid82/charon/backend/cmd/seed"
    "github.com/Wikid82/charon/backend/internal/logger"
    "github.com/Wikid82/charon/backend/internal/metrics"
    "github.com/Wikid82/charon/backend/internal/trace"
    "github.com/Wikid82/charon/backend/integration"
)

# Try to run tests to produce coverage file; some toolchains may return a non-zero
# exit if certain coverage tooling is unavailable (e.g. covdata) while still
# producing a usable coverage file. Capture the status so we can report real
# test failures after the coverage check.
# Note: Using -v for verbose output and -race for race detection
GO_TEST_STATUS=0
if ! go test -race -v -mod=readonly -coverprofile="$COVERAGE_FILE" ./...; then
    GO_TEST_STATUS=$?
fi

if [ "$GO_TEST_STATUS" -ne 0 ]; then
    echo "Warning: go test returned non-zero (status ${GO_TEST_STATUS}); checking coverage file presence"
fi

# Filter out excluded packages from coverage file
if [ -f "$COVERAGE_FILE" ]; then
    FILTERED_COVERAGE="${COVERAGE_FILE}.filtered"
    cp "$COVERAGE_FILE" "$FILTERED_COVERAGE"
    for pkg in "${EXCLUDE_PACKAGES[@]}"; do
        sed -i "\|^${pkg}|d" "$FILTERED_COVERAGE"
    done
    mv "$FILTERED_COVERAGE" "$COVERAGE_FILE"
fi

if [ ! -f "$COVERAGE_FILE" ]; then
    echo "Error: coverage file not generated by go test"
    exit 1
fi

go tool cover -func="$COVERAGE_FILE" | tail -n 1
TOTAL_LINE=$(go tool cover -func="$COVERAGE_FILE" | grep total)
TOTAL_PERCENT=$(echo "$TOTAL_LINE" | awk '{print substr($3, 1, length($3)-1)}')

echo "Computed coverage: ${TOTAL_PERCENT}% (minimum required ${MIN_COVERAGE}%)"

export TOTAL_PERCENT
export MIN_COVERAGE

python3 - <<'PY'
import os, sys
from decimal import Decimal

total = Decimal(os.environ['TOTAL_PERCENT'])
minimum = Decimal(os.environ['MIN_COVERAGE'])
if total < minimum:
    print(f"Coverage {total}% is below required {minimum}% (set CHARON_MIN_COVERAGE or CPM_MIN_COVERAGE to override)", file=sys.stderr)
    sys.exit(1)
PY

echo "Coverage requirement met"

# Bubble up real test failures (after printing coverage info) so pre-commit
# reflects the actual test status.
if [ "$GO_TEST_STATUS" -ne 0 ]; then
    exit "$GO_TEST_STATUS"
fi
