#!/bin/bash
#
# Pre-commit hook for knots
# Checks complexity of C, C++, Rust, Python, and JavaScript files being committed
#
# Installation:
#   cp pre-commit .git/hooks/pre-commit
#   chmod +x .git/hooks/pre-commit
#

# Configuration (can be overridden via git config)
MCCABE_THRESHOLD=${MCCABE_THRESHOLD:-$(git config hooks.knots.mccabe-threshold || echo "15")}
COGNITIVE_THRESHOLD=${COGNITIVE_THRESHOLD:-$(git config hooks.knots.cognitive-threshold || echo "15")}
NESTING_THRESHOLD=${NESTING_THRESHOLD:-$(git config hooks.knots.nesting-threshold || echo "5")}
SLOC_THRESHOLD=${SLOC_THRESHOLD:-$(git config hooks.knots.sloc-threshold || echo "50")}
ABC_THRESHOLD=${ABC_THRESHOLD:-$(git config hooks.knots.abc-threshold || echo "10.0")}
RETURN_THRESHOLD=${RETURN_THRESHOLD:-$(git config hooks.knots.return-threshold || echo "3")}
VALIDATOR_PATH=${VALIDATOR_PATH:-$(git config hooks.knots.path || which knots)}
VERBOSE=${VERBOSE:-$(git config hooks.knots.verbose || echo "false")}

# Colors for output
RED='\033[0;31m'
YELLOW='\033[1;33m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color

# Check if knots is installed
if [ ! -x "$VALIDATOR_PATH" ]; then
    echo -e "${YELLOW}Warning: knots not found at $VALIDATOR_PATH${NC}"
    echo "Install it or set the path with: git config hooks.knots.path /path/to/knots"
    echo "Skipping complexity check..."
    exit 0
fi

# Get list of supported source files being committed
C_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(c|cpp|cc|cxx|h|hpp|hxx|rs|py|js|mjs|cjs)$')

if [ -z "$C_FILES" ]; then
    # No supported source files in this commit
    exit 0
fi

echo "Running knots on staged files..."
echo ""

FAILED=0
WARNINGS=0

for file in $C_FILES; do
    if [ ! -f "$file" ]; then
        continue
    fi
    
    # Run knots on the file (always verbose for per-function details)
    OUTPUT=$($VALIDATOR_PATH -v "$file" 2>&1)
    
    # Parse output for complexity violations
    while IFS= read -r line; do
        # Stop parsing at Summary section
        if echo "$line" | grep -q "^Summary:"; then
            break
        fi

        if echo "$line" | grep -q "Function:"; then
            # Extract function name and remove emoji (emojis are at the end)
            CURRENT_FUNCTION=$(echo "$line" | sed 's/Function: //' | sed 's/ [😊😐😠😢]$//')
        elif echo "$line" | grep -q "  McCabe Complexity:"; then
            MCCABE=$(echo "$line" | awk '{print $3}')
            if [[ "$MCCABE" =~ ^[0-9]+$ ]] && [ "$MCCABE" -gt "$MCCABE_THRESHOLD" ]; then
                echo -e "${RED}✗ $file:$CURRENT_FUNCTION${NC}"
                echo "  McCabe Complexity: $MCCABE (threshold: $MCCABE_THRESHOLD)"
                FAILED=1
            fi
        elif echo "$line" | grep -q "  Cognitive Complexity:"; then
            COGNITIVE=$(echo "$line" | awk '{print $3}')
            if [[ "$COGNITIVE" =~ ^[0-9]+$ ]] && [ "$COGNITIVE" -gt "$COGNITIVE_THRESHOLD" ]; then
                echo -e "${RED}✗ $file:$CURRENT_FUNCTION${NC}"
                echo "  Cognitive Complexity: $COGNITIVE (threshold: $COGNITIVE_THRESHOLD)"
                FAILED=1
            fi
        elif echo "$line" | grep -q "  Nesting Depth:"; then
            NESTING=$(echo "$line" | awk '{print $3}')
            if [[ "$NESTING" =~ ^[0-9]+$ ]] && [ "$NESTING" -gt "$NESTING_THRESHOLD" ]; then
                echo -e "${RED}✗ $file:$CURRENT_FUNCTION${NC}"
                echo "  Nesting Depth: $NESTING (threshold: $NESTING_THRESHOLD)"
                FAILED=1
            fi
        elif echo "$line" | grep -q "  SLOC:"; then
            SLOC=$(echo "$line" | awk '{print $2}')
            if [[ "$SLOC" =~ ^[0-9]+$ ]] && [ "$SLOC" -gt "$SLOC_THRESHOLD" ]; then
                echo -e "${RED}✗ $file:$CURRENT_FUNCTION${NC}"
                echo "  SLOC: $SLOC (threshold: $SLOC_THRESHOLD)"
                FAILED=1
            fi
        elif echo "$line" | grep -q "  ABC:"; then
            # Extract ABC magnitude from line like "ABC: <2,4,5> (magnitude: 6.71)"
            ABC_MAG=$(echo "$line" | sed -n 's/.*magnitude: \([0-9.]*\).*/\1/p')
            if [[ "$ABC_MAG" =~ ^[0-9]+\.?[0-9]*$ ]]; then
                if [ $(echo "$ABC_MAG > $ABC_THRESHOLD" | bc -l) -eq 1 ]; then
                    echo -e "${RED}✗ $file:$CURRENT_FUNCTION${NC}"
                    echo "  ABC Magnitude: $ABC_MAG (threshold: $ABC_THRESHOLD)"
                    FAILED=1
                fi
            fi
        elif echo "$line" | grep -q "  Return Count:"; then
            RETURN_COUNT=$(echo "$line" | awk '{print $3}')
            if [[ "$RETURN_COUNT" =~ ^[0-9]+$ ]] && [ "$RETURN_COUNT" -gt "$RETURN_THRESHOLD" ]; then
                echo -e "${RED}✗ $file:$CURRENT_FUNCTION${NC}"
                echo "  Return Count: $RETURN_COUNT (threshold: $RETURN_THRESHOLD)"
                FAILED=1
            fi
        fi
    done <<< "$OUTPUT"
    
    # Show summary if verbose
    if [ "$VERBOSE" = "true" ]; then
        echo "$OUTPUT" | grep -A 5 "Summary:"
        echo ""
    fi
done

if [ $FAILED -eq 1 ]; then
    echo ""
    echo -e "${RED}Commit rejected: Complexity thresholds exceeded${NC}"
    echo ""
    echo "To adjust thresholds, run:"
    echo "  git config hooks.knots.mccabe-threshold <value>"
    echo "  git config hooks.knots.cognitive-threshold <value>"
    echo "  git config hooks.knots.nesting-threshold <value>"
    echo "  git config hooks.knots.sloc-threshold <value>"
    echo "  git config hooks.knots.abc-threshold <value>"
    echo "  git config hooks.knots.return-threshold <value>"
    echo ""
    echo "To bypass this check (not recommended), use:"
    echo "  git commit --no-verify"
    exit 1
else
    echo -e "${GREEN}✓ All complexity checks passed${NC}"
    exit 0
fi
