#!/usr/bin/env bash
set -euo pipefail
#
# Copyright 2026 ResQ
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# pre-commit
#
# Runs checks before allowing a commit:
#   resq CLI (if installed) → secrets scan → OSV vuln scan → ruff format/lint
#
# Install resq CLI: cargo install resq-cli
#
# Exit codes:
#   0  All checks passed.
#   1  Blocking check failed.

# ── Path resolution ───────────────────────────────────────────────────────────
if [ ${#BASH_SOURCE[@]} -gt 0 ] && [ -n "${BASH_SOURCE[0]:-}" ]; then
    HOOK_PATH="${BASH_SOURCE[0]}"
else
    HOOK_PATH="$0"
fi
HOOK_PATH=$(readlink -f "$HOOK_PATH")
SCRIPT_DIR=$(dirname "$HOOK_PATH")
PROJECT_ROOT=$(cd "$SCRIPT_DIR/.." && pwd)

# ── Nix environment entry (if osv-scanner or uv missing) ─────────────────────
if [[ -z "${IN_NIX_SHELL:-}" ]] && [[ -z "${RESQ_NIX_GUARD:-}" ]]; then
    NEED_NIX=0
    for _tool in osv-scanner uv; do
        if ! command -v "$_tool" >/dev/null 2>&1; then NEED_NIX=1; break; fi
    done
    if [[ "$NEED_NIX" -eq 1 ]] && command -v nix >/dev/null 2>&1 && [ -f "$PROJECT_ROOT/flake.nix" ]; then
        echo "❄️  Entering Nix environment for pre-commit checks..."
        export RESQ_NIX_GUARD=1
        exec nix develop "$PROJECT_ROOT" --command bash "$HOOK_PATH" "$@"
    fi
fi

if [ -f "$PROJECT_ROOT/scripts/lib/shell-utils.sh" ]; then
    source "$PROJECT_ROOT/scripts/lib/shell-utils.sh"
fi

[ -n "${GIT_HOOKS_SKIP:-}" ] && exit 0

# ── Try resq CLI ──────────────────────────────────────────────────────────────
if command -v resq >/dev/null 2>&1; then
    exec resq pre-commit --root "$PROJECT_ROOT" "$@"
fi
echo "ℹ️  resq CLI not found — running inline checks. Install: cargo install resq-cli"

# ── Large file check ──────────────────────────────────────────────────────────
echo "🔍 Checking staged file sizes..."
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
for f in $STAGED_FILES; do
    if [ -f "$f" ]; then
        SIZE=$(wc -c < "$f")
        if [ "$SIZE" -gt 1048576 ]; then
            echo "❌ '$f' exceeds 1 MB. Large files must not be committed."
            exit 1
        fi
    fi
done
echo "✅ File sizes OK"

# ── Secrets scan ──────────────────────────────────────────────────────────────
echo "🔍 Scanning for secrets..."
if command -v gitleaks >/dev/null 2>&1; then
    if ! gitleaks protect --staged --redact -v 2>/dev/null; then
        echo "❌ Potential secrets detected. Remove them before committing."
        exit 1
    fi
else
    STAGED_CONTENT=$(git diff --cached --unified=0 2>/dev/null || true)
    echo "$STAGED_CONTENT" | grep -qE 'AKIA[0-9A-Z]{16}'                          && { echo "❌ AWS key detected.";      exit 1; } || true
    echo "$STAGED_CONTENT" | grep -qE '(ghp_|ghs_|gho_)[A-Za-z0-9_]{36,}'        && { echo "❌ GitHub token detected."; exit 1; } || true
    echo "$STAGED_CONTENT" | grep -qF 'BEGIN PRIVATE KEY'                         && { echo "❌ Private key detected.";  exit 1; } || true
    echo "$STAGED_CONTENT" | grep -qiE 'api[_-]?key\s*=\s*"[A-Za-z0-9_\-]{16,}"' && { echo "❌ API key detected.";     exit 1; } || true
    echo "$STAGED_CONTENT" | grep -qiE 'password\s*=\s*"[^"]{4,}"'               && { echo "❌ Password detected.";    exit 1; } || true
fi
echo "✅ Secrets scan OK"

# ── OSV vulnerability scan ────────────────────────────────────────────────────
if command -v osv-scanner >/dev/null 2>&1; then
    echo "🔍 Running OSV vulnerability scan..."
    OSV_ARGS=()
    [ -f "$PROJECT_ROOT/uv.lock" ]           && OSV_ARGS+=(--lockfile "$PROJECT_ROOT/uv.lock")
    [ -f "$PROJECT_ROOT/requirements.txt" ]  && OSV_ARGS+=(--lockfile "$PROJECT_ROOT/requirements.txt")
    if [ ${#OSV_ARGS[@]} -gt 0 ]; then
        if ! osv-scanner scan "${OSV_ARGS[@]}" 2>/dev/null; then
            echo "❌ OSV scan found vulnerabilities. Run: osv-scanner scan --lockfile uv.lock"
            echo "   To skip: GIT_HOOKS_SKIP=1 git commit"
            exit 1
        fi
        echo "✅ OSV scan OK"
    fi
fi

# ── Python formatting and lint ────────────────────────────────────────────────
STAGED_PY=$(git diff --cached --name-only --diff-filter=ACM | grep '\.py$' || true)
if [ -n "$STAGED_PY" ] && command -v uv >/dev/null 2>&1; then
    echo "🔍 Formatting Python files with ruff..."
    # shellcheck disable=SC2086
    uv run ruff format $STAGED_PY 2>/dev/null || true
    # shellcheck disable=SC2086
    git add $STAGED_PY 2>/dev/null || true
    echo "🔍 Checking Python lint..."
    # shellcheck disable=SC2086
    if ! uv run ruff check $STAGED_PY 2>/dev/null; then
        echo "❌ Ruff lint errors. Run: uv run ruff check --fix src/"
        exit 1
    fi
    echo "✅ Python checks OK"
fi

echo "✅ Pre-commit checks passed"
