#!/bin/bash
# Hook: PreToolUse - Block dangerous actions
# Exit 0 = allow, Exit 2 = block (stderr message shown to Claude)
#
# Place in: .claude/hooks/dangerous-actions-blocker.sh
# Register in: .claude/settings.json under PreToolUse event

set -e

# Read JSON from stdin
INPUT=$(cat)

TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
TOOL_INPUT=$(echo "$INPUT" | jq -r '.tool_input // empty')

# === BASH: Dangerous commands ===
if [[ "$TOOL_NAME" == "Bash" ]]; then
    COMMAND=$(echo "$TOOL_INPUT" | jq -r '.command // empty')

    # Dangerous patterns
    DANGEROUS_PATTERNS=(
        "rm -rf /"
        "rm -rf ~"
        "rm -rf \$HOME"
        "dd if="
        "mkfs"
        ":(){:|:&};:"          # Fork bomb
        "> /dev/sda"
        "chmod -R 777 /"
        "chown -R"
        "sudo rm"
        "DROP DATABASE"
        "DROP TABLE"
        "--no-preserve-root"
    )

    for pattern in "${DANGEROUS_PATTERNS[@]}"; do
        if [[ "$COMMAND" == *"$pattern"* ]]; then
            echo "BLOCKED: Dangerous command detected: '$pattern'" >&2
            exit 2
        fi
    done

    # Block force push to main/master
    if echo "$COMMAND" | grep -qE "git push.*(-f|--force).*(main|master)"; then
        echo "BLOCKED: Force push to main/master is forbidden" >&2
        exit 2
    fi

    # Block npm publish without confirmation
    if echo "$COMMAND" | grep -qE "npm publish|pnpm publish|yarn publish"; then
        echo "BLOCKED: Package publication requires manual confirmation" >&2
        exit 2
    fi

    # Check for potential secrets in command
    SECRET_PATTERNS=(
        "password="
        "secret="
        "api_key="
        "apikey="
        "token="
        "aws_access_key"
        "aws_secret"
        "private_key"
    )

    for pattern in "${SECRET_PATTERNS[@]}"; do
        if echo "$COMMAND" | grep -qi "$pattern"; then
            echo "BLOCKED: Potential secret detected in command: '$pattern'" >&2
            exit 2
        fi
    done
fi

# === EDIT/WRITE: Sensitive files ===
if [[ "$TOOL_NAME" == "Edit" || "$TOOL_NAME" == "Write" ]]; then
    FILE_PATH=$(echo "$TOOL_INPUT" | jq -r '.file_path // empty')

    # Protected files
    PROTECTED_FILES=(
        ".env"
        ".env.local"
        ".env.production"
        ".env.development"
        "credentials.json"
        "serviceAccountKey.json"
        "id_rsa"
        "id_ed25519"
        "id_ecdsa"
        ".npmrc"
        ".pypirc"
        "secrets.yml"
        "secrets.yaml"
    )

    FILENAME=$(basename "$FILE_PATH")
    for protected in "${PROTECTED_FILES[@]}"; do
        if [[ "$FILENAME" == "$protected" ]]; then
            echo "BLOCKED: Editing sensitive file '$FILENAME' is forbidden" >&2
            exit 2
        fi
    done

    # Block editing outside project (with configurable exceptions)
    PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
    CLAUDE_HOME="${HOME}/.claude"

    # Allowed paths (configurable via environment variable)
    # Format: colon-separated paths - e.g., ALLOWED_PATHS="/custom/path:/other/path"
    EXTRA_ALLOWED="${ALLOWED_PATHS:-}"

    # Check if path is allowed
    is_allowed=false

    # Current project
    [[ "$FILE_PATH" == "$PROJECT_DIR"* ]] && is_allowed=true

    # Claude Code directory (~/.claude/) - plans, logs, settings
    [[ "$FILE_PATH" == "$CLAUDE_HOME"* ]] && is_allowed=true

    # Temporary files
    [[ "$FILE_PATH" == "/tmp"* ]] && is_allowed=true

    # Additional configured paths
    if [[ -n "$EXTRA_ALLOWED" ]]; then
        IFS=':' read -ra EXTRA_PATHS <<< "$EXTRA_ALLOWED"
        for allowed_path in "${EXTRA_PATHS[@]}"; do
            [[ "$FILE_PATH" == "$allowed_path"* ]] && is_allowed=true
        done
    fi

    if [[ "$is_allowed" == "false" ]]; then
        echo "BLOCKED: Editing outside project is forbidden: $FILE_PATH" >&2
        echo "Allowed paths: $PROJECT_DIR, $CLAUDE_HOME, /tmp" >&2
        [[ -n "$EXTRA_ALLOWED" ]] && echo "Additional allowed: $EXTRA_ALLOWED" >&2
        exit 2
    fi
fi

# === DELETE: Always warn ===
if [[ "$TOOL_NAME" == "Bash" ]]; then
    COMMAND=$(echo "$TOOL_INPUT" | jq -r '.command // empty')
    if echo "$COMMAND" | grep -qE "rm -r|rmdir|unlink"; then
        # Warning but not blocking (exit 0)
        echo '{"systemMessage": "Warning: File deletion detected. Verify this is intentional."}'
    fi
fi

# Allow by default
exit 0
