#!/bin/bash
set -u

REPO_ROOT="$(git rev-parse --show-toplevel)"
CONFIG_FILE="$REPO_ROOT/.inertia/config"

if [ ! -f "$CONFIG_FILE" ]; then
    echo "[INERTIA] No .inertia/config found. Push allowed."
    exit 0
fi

# shellcheck source=/dev/null
source "$CONFIG_FILE"

API_BASE="${API_BASE:-http://localhost:8000}"
PROJECT_ID="${PROJECT_ID:-}"
STUDENT_ID="${STUDENT_ID:-$(git config user.email)}"

detect_python() {
    if [ -n "${PYTHON_BIN:-}" ]; then
        if [ "$PYTHON_BIN" = "py -3" ]; then
            if py -3 -c "import sys; sys.exit(0 if sys.version_info.major >= 3 else 1)" >/dev/null 2>&1; then
                return 0
            fi
        else
            if "$PYTHON_BIN" -c "import sys; sys.exit(0 if sys.version_info.major >= 3 else 1)" >/dev/null 2>&1; then
                return 0
            fi
        fi
    fi

    if command -v python3 >/dev/null 2>&1; then
        if python3 -c "import sys; sys.exit(0 if sys.version_info.major >= 3 else 1)" >/dev/null 2>&1; then
            PYTHON_BIN="python3"
            return 0
        fi
    fi

    if command -v python >/dev/null 2>&1; then
        if python -c "import sys; sys.exit(0 if sys.version_info.major >= 3 else 1)" >/dev/null 2>&1; then
            PYTHON_BIN="python"
            return 0
        fi
    fi

    if command -v py >/dev/null 2>&1; then
        if py -3 -c "import sys; sys.exit(0 if sys.version_info.major >= 3 else 1)" >/dev/null 2>&1; then
            PYTHON_BIN="py -3"
            return 0
        fi
    fi

    return 1
}

if ! detect_python; then
    echo "[INERTIA] Warning: Python 3 is required but could not be found."
    echo "[INERTIA] Please install Python 3 or set PYTHON_BIN in your shell profile."
    echo "[INERTIA] Push allowed (offline mode / graceful degradation)."
    exit 0
fi

run_python() {
    if [ "$PYTHON_BIN" = "py -3" ]; then
        py -3 "$@"
    else
        "$PYTHON_BIN" "$@"
    fi
}

if [ -z "$PROJECT_ID" ] || [ -z "$STUDENT_ID" ]; then
    echo "[INERTIA] Missing PROJECT_ID or STUDENT_ID in .inertia/config. Push allowed."
    exit 0
fi

echo "[INERTIA] Analyzing commit..."

EMPTY_TREE=$(git hash-object -t tree /dev/null)
DIFF=""
LAST_PUSHED_SHA=""
READ_REFS=0

while IFS=' ' read -r local_ref local_sha remote_ref remote_sha; do
    [ -z "$local_sha" ] && continue
    READ_REFS=1

    # Deletion push; no new code to analyze
    if [[ "$local_sha" =~ ^0+$ ]]; then
        continue
    fi

    LAST_PUSHED_SHA="$local_sha"

    if [[ "$remote_sha" =~ ^0+$ ]]; then
        RANGE_DIFF=$(git diff "$EMPTY_TREE" "$local_sha")
    else
        RANGE_DIFF=$(git diff "$remote_sha" "$local_sha")
    fi

    if [ -n "$RANGE_DIFF" ]; then
        DIFF+="$RANGE_DIFF"
        DIFF+=$'\n'
    fi
done

# Fallback for environments that don't pass refs to hook stdin
if [ "$READ_REFS" -eq 0 ]; then
    if git rev-parse --verify HEAD^ >/dev/null 2>&1; then
        DIFF=$(git diff HEAD^ HEAD)
    else
        DIFF=$(git diff "$EMPTY_TREE" HEAD 2>/dev/null || true)
    fi
    LAST_PUSHED_SHA=$(git rev-parse HEAD 2>/dev/null || echo "")
fi

if [ -z "$DIFF" ]; then
    echo "[INERTIA] No diff detected. Push allowed."
    exit 0
fi

DIFF_JSON=$(printf '%s' "$DIFF" | run_python -c 'import json,sys; print(json.dumps(sys.stdin.read()))')
COMMIT_HASH=$(printf '%s' "$LAST_PUSHED_SHA" | cut -c1-7)
if [ -n "$LAST_PUSHED_SHA" ]; then
    COMMIT_MSG=$(git log -1 --pretty=%s "$LAST_PUSHED_SHA" 2>/dev/null || echo "")
else
    COMMIT_MSG=$(git log -1 --pretty=%s 2>/dev/null || echo "")
fi
COMMIT_MSG_JSON=$(printf '%s' "$COMMIT_MSG" | run_python -c 'import json,sys; print(json.dumps(sys.stdin.read()))')
COMMIT_HASH_JSON=$(printf '%s' "$COMMIT_HASH" | run_python -c 'import json,sys; print(json.dumps(sys.stdin.read()))')

AUDIT_RESPONSE=$(curl -s -X POST "$API_BASE/audit" \
    -H "Content-Type: application/json" \
    -d "{\"diff\": $DIFF_JSON, \"student_id\": \"$STUDENT_ID\", \"project_id\": \"$PROJECT_ID\", \"commit_hash\": $COMMIT_HASH_JSON, \"commit_message\": $COMMIT_MSG_JSON}")

if [ $? -ne 0 ] || [ -z "$AUDIT_RESPONSE" ]; then
    echo "[INERTIA] Cannot reach server. Push allowed (offline mode)."
    exit 0
fi

# Check if the server returned an error array/message (e.g. 423 Locked Out)
ERROR_DETAIL=$(printf '%s' "$AUDIT_RESPONSE" | run_python -c "import json,sys; d=json.load(sys.stdin); print(d.get('detail', '')) if isinstance(d, dict) else print('')" 2>/dev/null)
if [ -n "$ERROR_DETAIL" ]; then
    echo "[INERTIA] $ERROR_DETAIL"
    echo "[INERTIA] Push blocked."
    exit 1
fi

FC_SCORE=$(printf '%s' "$AUDIT_RESPONSE" | run_python -c "import json,sys; print(json.load(sys.stdin).get('complexity_score', 0))")
REQUIRES_PUZZLE=$(printf '%s' "$AUDIT_RESPONSE" | run_python -c "import json,sys; print(json.load(sys.stdin).get('requires_puzzle', False))")

if [ "$REQUIRES_PUZZLE" != "True" ]; then
    echo "[INERTIA] Trivial commit. Push allowed."
    exit 0
fi

DIFFICULTY=$(printf '%s' "$AUDIT_RESPONSE" | run_python -c "import json,sys; print(json.load(sys.stdin).get('difficulty', 'EASY'))")

PUZZLE_RESPONSE=$(curl -sf -X POST "$API_BASE/puzzle" \
    -H "Content-Type: application/json" \
    -d "{\"diff\": $DIFF_JSON, \"fc_score\": $FC_SCORE, \"difficulty\": \"$DIFFICULTY\", \"student_id\": \"$STUDENT_ID\", \"project_id\": \"$PROJECT_ID\", \"commit_hash\": $COMMIT_HASH_JSON, \"commit_message\": $COMMIT_MSG_JSON}")

if [ $? -ne 0 ] || [ -z "$PUZZLE_RESPONSE" ]; then
    echo "[INERTIA] Puzzle request failed. Push blocked."
    exit 1
fi

TOKEN_ID=$(printf '%s' "$PUZZLE_RESPONSE" | run_python -c "import json,sys; print(json.load(sys.stdin).get('token_id', ''))")
TIMER=$(printf '%s' "$PUZZLE_RESPONSE" | run_python -c "import json,sys; print(json.load(sys.stdin).get('timer_seconds', 0))")

FRONTEND_URL="${FRONTEND_URL:-https://inertia-tau.vercel.app}"
PUZZLE_URL="${FRONTEND_URL}/student?token=${TOKEN_ID}"

echo ""
echo "========================================"
echo "INERTIA: PROOF-OF-THOUGHT REQUIRED"
echo "========================================"
echo ""
echo "  Open this URL in your browser and solve the puzzle:"
echo ""
echo "  $PUZZLE_URL"
echo ""
echo "  Time limit: ${TIMER}s"
echo "  Waiting for verification..."
echo "========================================"

# Poll /puzzle/{token_id}/status until verified, expired, or timer runs out
POLL_INTERVAL=3
ELAPSED=0

while [ "$ELAPSED" -lt "$TIMER" ]; do
    sleep $POLL_INTERVAL
    ELAPSED=$((ELAPSED + POLL_INTERVAL))

    STATUS_RESPONSE=$(curl -sf "$API_BASE/puzzle/${TOKEN_ID}/status")
    if [ $? -ne 0 ] || [ -z "$STATUS_RESPONSE" ]; then
        continue
    fi

    STATUS=$(printf '%s' "$STATUS_RESPONSE" | run_python -c "import json,sys; print(json.load(sys.stdin).get('status', ''))")

    if [ "$STATUS" = "verified" ]; then
        echo ""
        echo "[INERTIA] Proof-of-Thought verified. Push proceeding."
        exit 0
    fi

    if [ "$STATUS" = "expired" ]; then
        echo ""
        echo "[INERTIA] Puzzle expired or failed. Push blocked. Try pushing again."
        exit 1
    fi

    REMAINING=$((TIMER - ELAPSED))
    printf "\r[INERTIA] Waiting... %ds remaining   " "$REMAINING"
done

echo ""
echo "[INERTIA] Timed out waiting for verification. Push blocked."
exit 1
