#!/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:-${INERTIA_API:-http://localhost:8000}}"
FRONTEND_URL="${FRONTEND_URL:-https://inertia-tau.vercel.app}"
PROJECT_ID="${PROJECT_ID:-}"
STUDENT_ID="${STUDENT_ID:-$(git config user.email)}"

# Detect Python binary: honour config, then try python3, python, py
if [ -z "${PYTHON_BIN:-}" ]; then
    if command -v python3 >/dev/null 2>&1; then
        PYTHON_BIN="python3"
    elif command -v python >/dev/null 2>&1 && python -c "import sys; assert sys.version_info[0]==3" 2>/dev/null; then
        PYTHON_BIN="python"
    elif command -v py >/dev/null 2>&1; then
        PYTHON_BIN="py -3"
    else
        echo "[INERTIA] Python 3 not found. Push allowed. Install Python 3 or set PYTHON_BIN in .inertia/config."
        exit 0
    fi
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

    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

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" | $PYTHON_BIN -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" | $PYTHON_BIN -c 'import json,sys; print(json.dumps(sys.stdin.read()))')
COMMIT_HASH_JSON=$(printf '%s' "$COMMIT_HASH" | $PYTHON_BIN -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" | $PYTHON_BIN -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" | $PYTHON_BIN -c "import json,sys; print(json.load(sys.stdin).get('complexity_score', 0))")
REQUIRES_PUZZLE=$(printf '%s' "$AUDIT_RESPONSE" | $PYTHON_BIN -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" | $PYTHON_BIN -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" | $PYTHON_BIN -c "import json,sys; print(json.load(sys.stdin).get('token_id', ''))")
TIMER=$(printf '%s' "$PUZZLE_RESPONSE" | $PYTHON_BIN -c "import json,sys; print(json.load(sys.stdin).get('timer_seconds', 120))")

if [ -z "$TOKEN_ID" ]; then
    echo "[INERTIA] No token received from server. Push blocked."
    exit 1
fi

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" | $PYTHON_BIN -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
