#!/bin/bash

set -e

function run_pkg_test {
    # This could be swapped for pkgconf
    PC="pkg-config"

    echo "=== Testing $PC for $PC_MODULE_NAME ==="

    # Check if the module exists
    echo "Test 1: Checking if module exists..."
    $PC --exists "$PC_MODULE_NAME"

    # Test 2: Validate the .pc file
    echo ""
    echo "Test 2: Validating .pc file..."
    $PC --validate "$PC_MODULE_NAME"

    # Test 3: Get version
    echo ""
    echo "Test 3: Getting version..."
    VERSION=$($PC --modversion "$PC_MODULE_NAME")
    if [ -z "$VERSION" ]; then
        echo "Failed to get version"
        exit 1
    fi

    if [ "$VERSION" != "$CUDA_MAJOR.$CUDA_MINOR" ]; then
        echo "Module version mismatch:"
        echo "  Expected: $CUDA_MAJOR.$CUDA_MINOR"
        echo "  Got: $VERSION"
        exit 1
    fi
    echo "Version retrieved successfully: $VERSION"

    # Test 4: Get cflags
    echo ""
    echo "Test 4: Getting cflags..."
    CFLAGS=$($PC --cflags "$PC_MODULE_NAME")
    echo "CFLAGS: $CFLAGS"
    if [ -z "$CFLAGS" ]; then
        echo "Failed to get cflags"
        exit 1
    fi
    # Check that cflags contain -I flag
    if ! echo "$CFLAGS" | grep -q -- "-I"; then
        echo "CFLAGS does not contain -I flag"
        exit 1
    fi
    echo "CFLAGS retrieved successfully"

    # Test 5: Get libs
    echo ""
    echo "Test 5: Getting libs..."
    LIBS=$($PC --libs "$PC_MODULE_NAME")
    echo "LIBS: $LIBS"
    if [ -z "$LIBS" ]; then
        echo "Failed to get libs"
        exit 1
    fi
    # Check that libs contain -l flag
    if ! echo "$LIBS" | grep -q -- "-l"; then
        echo "LIBS does not contain -l flag"
        exit 1
    fi
    echo "LIBS retrieved successfully"

    # Test 6: Get variables
    echo ""
    echo "Test 6: Getting pkg-config variables..."
    CUDAROOT=$($PC --variable=cudaroot "$PC_MODULE_NAME")
    echo "cudaroot: $CUDAROOT"
    if [ -z "$CUDAROOT" ]; then
        echo "Failed to get cudaroot variable"
        exit 1
    fi
    echo "cudaroot variable retrieved successfully"

    LIBDIR=$($PC --variable=libdir "$PC_MODULE_NAME")
    echo "libdir: $LIBDIR"
    if [ -z "$LIBDIR" ]; then
        echo "Failed to get libdir variable"
        exit 1
    fi
    echo "libdir variable retrieved successfully"

    INCLUDEDIR=$($PC --variable=includedir "$PC_MODULE_NAME")
    echo "includedir: $INCLUDEDIR"
    if [ -z "$INCLUDEDIR" ]; then
        echo "Failed to get includedir variable"
        exit 1
    fi
    echo "includedir variable retrieved successfully"

    # Test 7: Check that the include directory exists and contains headers
    echo ""
    echo "Test 7: Checking if include directory $INCLUDEDIR exists and contains headers..."
    if [ ! -d "$INCLUDEDIR" ]; then
        echo "Include directory does not exist: $INCLUDEDIR"
        tree "$CUDAROOT"
        exit 1
    fi
    echo "Include directory exists: $INCLUDEDIR"

    # Look for header files
    case "$BASE_NAME" in
        nppial|nppicc|nppidei|nppif|nppig|nppim|nppist|nppisu|nppitc|npps)
            BASE_NAME="npp"
            ;;
    esac

    HEADER_COUNT=$(find "$INCLUDEDIR" -iname "$BASE_NAME*.h" | wc -l)
    if [ "$HEADER_COUNT" -eq 0 ]; then
        echo "No $BASE_NAME headers found in $INCLUDEDIR"
        tree "$CUDAROOT"
        exit 1
    fi
    echo "Found $HEADER_COUNT $BASE_NAME header file(s)"

    # Test 8: Check that the lib directory exists and contains library files
    echo ""
    echo "Test 8: Checking if lib directory exists..."
    if [ ! -d "$LIBDIR" ]; then
        echo "Lib directory does not exist: $LIBDIR"
        tree "$CUDAROOT"
        exit 1
    fi
    echo "Lib directory exists: $LIBDIR"

    LIB_COUNT=$(find "$LIBDIR" -iname "$LIB_NAME*.so" -o -iname "$LIB_NAME*.a" | wc -l)
    if [ "$LIB_COUNT" -eq 0 ]; then
        echo "No $LIB_NAME library files found in $LIBDIR"
        tree "$CUDAROOT"
        exit 1
    fi
    echo "Found $LIB_COUNT $LIB_NAME library file(s)"
}

# Auto-detect source package name from debian/changelog
if [ -f debian/changelog ]; then
    SOURCE_PKG=$(dpkg-parsechangelog -S Source)
else
    echo "Error in test setup: cannot find debian/changelog"
    exit 1
fi

# For now, we assume there is a binary package with the same name as the source package
# Use this to get the binary package version
PKG_VERSION=$(dpkg-query -W -f='${Version}' "$SOURCE_PKG" 2>/dev/null | cut -d- -f1)
if [ -z "$PKG_VERSION" ]; then
    echo "Error in test setup: Failed to get package version for $SOURCE_PKG"
    exit 1
fi

# Auto-detect CUDA version from debian/cuda-version file
if [ -f debian/cuda-version ]; then
    CUDA_VERSION=$(cat debian/cuda-version)
else
    echo "Error in test setup: cannot detect CUDA version"
    exit 1
fi

CUDA_MAJOR=$(echo "$CUDA_VERSION" | cut -d. -f1)
CUDA_MINOR=$(echo "$CUDA_VERSION" | cut -d. -f2)

# libfoo-X-Y
LIB_NAME="${SOURCE_PKG%-*-*}"          # libfoo-X-Y -> libfoo 
BASE_NAME="${LIB_NAME#lib}"       # libfoo -> foo
PC_MODULE_BASE="${LIB_NAME#lib}"       # libfoo -> foo
PC_MODULE_NAME="$PC_MODULE_BASE-$CUDA_MAJOR.$CUDA_MINOR"

# some packages require tuning in the naming, or have several .pc files
case "$SOURCE_PKG" in
    cuda-nvrtc-*)
        BASE_NAME=nvrtc LIB_NAME=libnvrtc PC_MODULE_BASE=nvrtc PC_MODULE_NAME="nvrtc-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        ;;
    libnpp-*)
        BASE_NAME=nppc LIB_NAME=libnppc PC_MODULE_BASE=nppc PC_MODULE_NAME="nppc-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        BASE_NAME=nppi LIB_NAME=libnppi PC_MODULE_BASE=nppi PC_MODULE_NAME="nppi-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        BASE_NAME=nppial LIB_NAME=libnppial PC_MODULE_BASE=nppial PC_MODULE_NAME="nppial-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        BASE_NAME=nppicc LIB_NAME=libnppicc PC_MODULE_BASE=nppicc PC_MODULE_NAME="nppicc-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        BASE_NAME=nppidei LIB_NAME=libnppidei PC_MODULE_BASE=nppidei PC_MODULE_NAME="nppidei-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        BASE_NAME=nppif LIB_NAME=libnppif PC_MODULE_BASE=nppif PC_MODULE_NAME="nppif-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        BASE_NAME=nppig LIB_NAME=libnppig PC_MODULE_BASE=nppig PC_MODULE_NAME="nppig-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        BASE_NAME=nppim LIB_NAME=libnppim PC_MODULE_BASE=nppim PC_MODULE_NAME="nppim-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        BASE_NAME=nppist LIB_NAME=libnppist PC_MODULE_BASE=nppist PC_MODULE_NAME="nppist-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        BASE_NAME=nppisu LIB_NAME=libnppisu PC_MODULE_BASE=nppisu PC_MODULE_NAME="nppisu-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        BASE_NAME=nppitc LIB_NAME=libnppitc PC_MODULE_BASE=nppitc PC_MODULE_NAME="nppitc-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        BASE_NAME=npps LIB_NAME=libnpps PC_MODULE_BASE=npps PC_MODULE_NAME="npps-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        ;;
    cuda-nvml-dev*)
        BASE_NAME=nvml LIB_NAME=libnvidia-ml PC_MODULE_BASE=nvidia-ml PC_MODULE_NAME="nvidia-ml-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        ;;
    cuda-sandbox-dev*)
        BASE_NAME=nvsandboxutils LIB_NAME=libnvidia-sandboxutils PC_MODULE_BASE=nvsandboxutils PC_MODULE_NAME="nvsandboxutils-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        ;;
    cuda-opencl-*)
        BASE_NAME=opencl LIB_NAME=libOpenCL PC_MODULE_BASE=opencl PC_MODULE_NAME="opencl-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        ;;
    cuda-cudart-*)
        BASE_NAME=cudart LIB_NAME=libcudart PC_MODULE_BASE=cudart PC_MODULE_NAME="cudart-$CUDA_MAJOR.$CUDA_MINOR" run_pkg_test
        ;;
    *)
        run_pkg_test
        ;;
esac

echo ""
echo "=== All tests passed successfully ==="
