#!/bin/bash
# Git pre-push hook for HotPlex Worker
# Final guard before code leaves the local machine

set -e

# ANSI color codes
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'

printf "${YELLOW}🚀 Running pre-push validation...${NC}\n"

# 0. Block large files (>1MB) anywhere in the tree
# Scans ALL commits being pushed, not just working tree
REMOTE_REF="$1"
LOCAL_REF="$2"

# Find the range of commits being pushed
RANGE=""
if [ -n "$LOCAL_REF" ] && [ "$LOCAL_REF" != "0000000000000000000000000000000000000000" ]; then
    # Get merge base between local and remote
    MERGE_BASE=$(git merge-base "$LOCAL_REF" "$REMOTE_REF" 2>/dev/null || echo "")
    if [ -n "$MERGE_BASE" ]; then
        RANGE="$MERGE_BASE..$LOCAL_REF"
    else
        # New branch - check all commits
        RANGE="$LOCAL_REF"
    fi
fi

if [ -n "$RANGE" ]; then
    MAX_BLOB_SIZE=1048576  # 1MB
    OVERSIZED=""
    # List all blobs in the push range and check sizes
    while IFS= read -r blob_info; do
        size=$(echo "$blob_info" | awk '{print $3}')
        path=$(echo "$blob_info" | awk '{print $4}')
        if [ -n "$size" ] && [ "$size" -gt "$MAX_BLOB_SIZE" ] 2>/dev/null; then
            # Allow known binary asset directories
            case "$path" in
                assets/*|docs/asserts/*|docs/channels/*/guides/*) continue ;;
            esac
            OVERSIZED="$OVERSIZED\n  $path ($(( size / 1048576 ))MB)"
        fi
    done < <(git rev-list --objects "$RANGE" 2>/dev/null | git cat-file --batch-check='%(objecttype) %(objectsize) %(rest)' 2>/dev/null | awk '$1 == "blob" && $2 > 1048576 {print $0}')

    if [ -n "$OVERSIZED" ]; then
        printf "${RED}❌ Push blocked: files >1MB detected in push range:${NC}\n"
        printf "$OVERSIZED\n"
        printf "${YELLOW}Move to .gitignore, use Git LFS, or reduce file size.${NC}\n"
        exit 1
    fi
fi

# 1. Format check (gofmt + goimports)
# Catches formatting drift from rebase conflict resolution or manual edits.
printf "🔹 Checking formatting...\n"
make fmt > /dev/null 2>&1
if ! git diff --quiet; then
    printf "${RED}❌ make fmt modified files. Stage and commit the changes, then push again.${NC}\n"
    git diff --name-only
    exit 1
fi

# 2. Lint (golangci-lint including gofmt, goimports, staticcheck, etc.)
printf "🔹 Running linter...\n"
if ! make lint; then
    printf "${RED}❌ Lint failed! Fix the issues before pushing.${NC}\n"
    exit 1
fi

# 3. Vet (static analysis beyond lint)
printf "🔹 Running go vet...\n"
if ! go vet ./...; then
    printf "${RED}❌ go vet found issues! Fix before pushing.${NC}\n"
    exit 1
fi

# 4. Module integrity
printf "🔹 Verifying module checksums...\n"
if ! go mod verify; then
    printf "${RED}❌ Module checksums mismatch! Run 'go mod tidy' and check dependencies.${NC}\n"
    exit 1
fi

# 5. Build validation
printf "🔹 Verifying build...\n"
if ! make build > /dev/null 2>&1; then
    printf "${RED}❌ Build failed! Fix compilation errors before pushing.${NC}\n"
    make build
    exit 1
fi

# 6. Fast unit tests
printf "🔹 Running tests...\n"
if ! make test-short > /dev/null 2>&1; then
    printf "${RED}❌ Tests failed! Push aborted.${NC}\n"
    make test-short
    exit 1
fi

printf "${GREEN}✅ All quality gates passed! Push authorized.${NC}\n"
exit 0
