#!/bin/bash
#
# Secret Detection Pre-Commit Hook
#
# Dieses Skript prüft staged Dateien auf potenzielle Secrets.
# Installation: ln -sf ../../scripts/detect-secrets.sh .git/hooks/pre-commit
#

set -e

# Farben für Output
RED='\033[0;31m'
YELLOW='\033[1;33m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color

echo -e "${GREEN}🔍 Checking for secrets in staged files...${NC}"

# Patterns für potenzielle Secrets
PATTERNS=(
    # API Keys und Tokens
    'api[_-]?key\s*[:=]\s*["\x27][a-zA-Z0-9_-]{20,}["\x27]'
    'token\s*[:=]\s*["\x27][a-zA-Z0-9_-]{20,}["\x27]'

    # AWS
    'AKIA[0-9A-Z]{16}'
    'aws[_-]?secret[_-]?access[_-]?key'

    # Private Keys
    '-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----'

    # Passwörter in Code
    'password\s*[:=]\s*["\x27][^"\x27]{8,}["\x27]'
    'passwd\s*[:=]\s*["\x27][^"\x27]{8,}["\x27]'

    # SMTP Credentials
    'smtp[_-]?pass(word)?\s*[:=]\s*["\x27][^"\x27]+["\x27]'

    # Database URLs mit Passwörtern
    '(postgres|mysql|mongodb)://[^:]+:[^@]+@'

    # JWT Tokens (vollständige)
    'eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}'

    # Generic Secrets
    'secret\s*[:=]\s*["\x27][^"\x27]{16,}["\x27]'

    # Slack Webhooks
    'hooks\.slack\.com/services/T[A-Z0-9]{8}/B[A-Z0-9]{8}/[a-zA-Z0-9]{24}'

    # Discord Webhooks
    'discord(app)?\.com/api/webhooks/[0-9]+/[a-zA-Z0-9_-]+'

    # GitHub Tokens
    'ghp_[a-zA-Z0-9]{36}'
    'gho_[a-zA-Z0-9]{36}'
    'ghu_[a-zA-Z0-9]{36}'
    'ghs_[a-zA-Z0-9]{36}'

    # SendGrid
    'SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}'

    # Stripe
    'sk_(live|test)_[a-zA-Z0-9]{24,}'
    'pk_(live|test)_[a-zA-Z0-9]{24,}'
)

# Dateien die ignoriert werden sollen
IGNORE_FILES=(
    '\.min\.js$'
    '\.min\.css$'
    'package-lock\.json$'
    'pnpm-lock\.yaml$'
    'yarn\.lock$'
    '\.md$'
    '\.txt$'
    'detect-secrets\.sh$'
    '\.example$'
    '\.sample$'
    '\.spec\.ts$'  # Test files may contain example secrets for testing
    '\.test\.ts$'
    'db-direct\.sh$'  # Uses get_password() function for secure password input
    'setup-tenants/setup\.sh$'  # Uses environment variables, not hardcoded secrets
    'check-production-deploys\.sh$'  # References env var name CRON_SECRET, not actual secret
)

# Pfade die ignoriert werden sollen
IGNORE_PATHS=(
    'node_modules/'
    'dist/'
    '.next/'
    'coverage/'
    '.git/'
)

# Prüfe ob wir in einem Git-Repository sind
if ! git rev-parse --git-dir > /dev/null 2>&1; then
    echo -e "${RED}Error: Not a git repository${NC}"
    exit 1
fi

# Hole staged Dateien
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)

if [ -z "$STAGED_FILES" ]; then
    echo -e "${GREEN}✅ No staged files to check${NC}"
    exit 0
fi

FOUND_SECRETS=0

for file in $STAGED_FILES; do
    # Überspringe wenn Datei nicht existiert
    [ ! -f "$file" ] && continue

    # Überspringe ignorierte Pfade
    skip=false
    for ignore_path in "${IGNORE_PATHS[@]}"; do
        if [[ "$file" == *"$ignore_path"* ]]; then
            skip=true
            break
        fi
    done
    [ "$skip" = true ] && continue

    # Überspringe ignorierte Dateitypen
    for ignore_file in "${IGNORE_FILES[@]}"; do
        if [[ "$file" =~ $ignore_file ]]; then
            skip=true
            break
        fi
    done
    [ "$skip" = true ] && continue

    # Prüfe jedes Pattern
    for pattern in "${PATTERNS[@]}"; do
        # Hole nur die staged Version der Datei
        matches=$(git show ":$file" 2>/dev/null | grep -niE "$pattern" 2>/dev/null || true)

        if [ -n "$matches" ]; then
            echo -e "${RED}⚠️  Potential secret found in: $file${NC}"
            echo -e "${YELLOW}Pattern: $pattern${NC}"
            echo "$matches" | head -5
            echo ""
            FOUND_SECRETS=$((FOUND_SECRETS + 1))
        fi
    done
done

if [ $FOUND_SECRETS -gt 0 ]; then
    echo -e "${RED}❌ Found $FOUND_SECRETS potential secret(s)!${NC}"
    echo ""
    echo "If these are false positives, you can:"
    echo "  1. Add the file to IGNORE_FILES in scripts/detect-secrets.sh"
    echo "  2. Use 'git commit --no-verify' to skip this check (not recommended)"
    echo "  3. Move secrets to environment variables or .env files"
    echo ""
    exit 1
fi

echo -e "${GREEN}✅ No secrets found in staged files${NC}"
exit 0
