#!/usr/bin/env bash
set -euo pipefail

# Test the version-check / update-check behavior of codelogician.sh
#
# Usage: ./test_version_check.sh [API_URL]
#   API_URL defaults to http://localhost:8080
#
# Requires: bash, curl, jq, IMANDRA_UNI_KEY in env
#
# Steps:
#   1. Install codelogician.sh into a temp dir
#   2. Run --version → cache seeded; verify cache exists and is fresh
#   3. Edit cache: set cloud version to a fake mismatch value, keep fresh timestamp
#   4. Run "eval --help" → fresh cache, reads mismatch → warns
#   5. Make cache stale (timestamp > 24h ago)
#   6. Run "eval --help" → stale cache triggers re-fetch from real cloud → warns
#   7. Edit cache: fresh + matching local version; run "--version" → force-fetches → warns

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SHELL_SCRIPT="$SCRIPT_DIR/shell/codelogician.sh"
API_URL="${1:-http://localhost:8080}"

pass=0
fail=0
total=0

assert_contains() {
  local label="$1" haystack="$2" needle="$3"
  ((++total))
  if [[ "$haystack" == *"$needle"* ]]; then
    printf "  PASS: %s\n" "$label"
    ((++pass))
  else
    printf "  FAIL: %s\n" "$label"
    printf "    expected to contain: %s\n" "$needle"
    printf "    got: %s\n" "$haystack"
    ((++fail))
  fi
}

assert_not_contains() {
  local label="$1" haystack="$2" needle="$3"
  ((++total))
  if [[ "$haystack" != *"$needle"* ]]; then
    printf "  PASS: %s\n" "$label"
    ((++pass))
  else
    printf "  FAIL: %s\n" "$label"
    printf "    expected NOT to contain: %s\n" "$needle"
    printf "    got: %s\n" "$haystack"
    ((++fail))
  fi
}

assert_file_exists() {
  local label="$1" path="$2"
  ((++total))
  if [ -f "$path" ]; then
    printf "  PASS: %s\n" "$label"
    ((++pass))
  else
    printf "  FAIL: %s (file not found: %s)\n" "$label" "$path"
    ((++fail))
  fi
}

# ── Setup ──────────────────────────────────────────────────────────────

TMPDIR_ROOT=$(mktemp -d)
trap 'rm -rf "$TMPDIR_ROOT"' EXIT

INSTALL_DIR="$TMPDIR_ROOT/bin"
FAKE_HOME="$TMPDIR_ROOT/home"
CACHE_DIR="$FAKE_HOME/.cache/codelogician"
CACHE_FILE="$CACHE_DIR/update-check"

mkdir -p "$INSTALL_DIR" "$FAKE_HOME"

# Copy the real script
cp "$SHELL_SCRIPT" "$INSTALL_DIR/codelogician"
chmod +x "$INSTALL_DIR/codelogician"

# Read local version from the script's embedded SPEC
LOCAL_VERSION=$(jq -r '.__version__' <<<"$(sed -n "s/^SPEC='//;s/'$//p" "$SHELL_SCRIPT")")
FAKE_CLOUD_VERSION="99.99.99"
WARNING_NEEDLE="Warning: codelogician"

# Helper: run codelogician with isolated HOME (so cache goes to FAKE_HOME).
run_cl() {
  local out_file="$TMPDIR_ROOT/stdout" err_file="$TMPDIR_ROOT/stderr"
  HOME="$FAKE_HOME" \
  CODELOGICIAN_LITE_URL="$API_URL" \
    "$INSTALL_DIR/codelogician" "$@" >"$out_file" 2>"$err_file" || true
  STDOUT=$(cat "$out_file")
  STDERR=$(cat "$err_file")
}

echo "Local version: $LOCAL_VERSION"
echo "API URL: $API_URL"
echo

# ── Step 1: Install ───────────────────────────────────────────────────

echo "=== Step 1: Install ==="
assert_file_exists "codelogician binary installed" "$INSTALL_DIR/codelogician"

# ── Step 2: Run --version to seed cache ───────────────────────────────

echo
echo "=== Step 2: Run --version to seed cache ==="
run_cl --version

assert_contains "--version prints local version" "$STDOUT" "codelogician-lite-shell $LOCAL_VERSION"
assert_file_exists "cache file created" "$CACHE_FILE"

# Verify cache is fresh (timestamp within last 10 seconds)
cached_ts=$(head -1 "$CACHE_FILE")
now=$(date +%s)
age=$((now - cached_ts))
((++total))
if [ "$age" -lt 10 ]; then
  printf "  PASS: cache is fresh (age=%ds)\n" "$age"
  ((++pass))
else
  printf "  FAIL: cache is unexpectedly old (age=%ds)\n" "$age"
  ((++fail))
fi

# ── Step 3: Edit cache — fake mismatch version, still fresh ──────────

echo
echo "=== Step 3: Edit cache to fake mismatch (fresh) ==="
printf '%s\n%s\n' "$(date +%s)" "$FAKE_CLOUD_VERSION" > "$CACHE_FILE"
echo "  Cache now: ts=$(head -1 "$CACHE_FILE"), version=$(tail -1 "$CACHE_FILE")"

# ── Step 4: eval --help with fresh mismatched cache → warns ──────────

echo
echo "=== Step 4: eval --help (fresh cache, version mismatch) ==="
run_cl eval --help

assert_contains "update warning from cached mismatch" "$STDERR" "$WARNING_NEEDLE"
# Cache should NOT have been refreshed (still fresh, no re-fetch)
cached_ver_after=$(tail -1 "$CACHE_FILE")
assert_contains "cache still has fake version (no re-fetch)" "$cached_ver_after" "$FAKE_CLOUD_VERSION"

# ── Step 5: Make cache stale (>24h old) ───────────────────────────────

echo
echo "=== Step 5: Make cache stale ==="
stale_ts=$(( $(date +%s) - 90000 ))  # ~25 hours ago
printf '%s\n%s\n' "$stale_ts" "$FAKE_CLOUD_VERSION" > "$CACHE_FILE"
echo "  Cache now: ts=$stale_ts (25h ago), version=$FAKE_CLOUD_VERSION"

# ── Step 6: eval --help with stale cache → re-fetches from cloud ─────

echo
echo "=== Step 6: eval --help (stale cache → re-fetch from cloud) ==="
run_cl eval --help

# Cache timestamp should be refreshed
new_ts=$(head -1 "$CACHE_FILE")
((++total))
if [ "$new_ts" -gt "$stale_ts" ]; then
  printf "  PASS: cache timestamp refreshed (%s > %s)\n" "$new_ts" "$stale_ts"
  ((++pass))
else
  printf "  FAIL: cache timestamp not refreshed (%s <= %s)\n" "$new_ts" "$stale_ts"
  ((++fail))
fi

# Cache should now have the real cloud version (no longer the fake one)
real_cloud_ver=$(tail -1 "$CACHE_FILE")
assert_not_contains "cache no longer has fake version" "$real_cloud_ver" "$FAKE_CLOUD_VERSION"
echo "  Cloud version fetched: $real_cloud_ver"

# If real cloud version differs from local, there should be a warning
if [ "$real_cloud_ver" != "$LOCAL_VERSION" ]; then
  assert_contains "update warning after stale re-fetch" "$STDERR" "$WARNING_NEEDLE"
else
  echo "  (cloud version matches local — no warning expected)"
fi

# ── Step 7: Fresh + matching cache, but --version force-fetches ───────

echo
echo "=== Step 7: --version force-fetches even with fresh matching cache ==="
printf '%s\n%s\n' "$(date +%s)" "$LOCAL_VERSION" > "$CACHE_FILE"
echo "  Cache reset: ts=$(head -1 "$CACHE_FILE"), version=$LOCAL_VERSION (matches local)"

run_cl --version

assert_contains "--version prints local version" "$STDOUT" "codelogician-lite-shell $LOCAL_VERSION"

# Cache should now have the real cloud version (force-fetched), not the local one we wrote
force_ver=$(tail -1 "$CACHE_FILE")
echo "  Cloud version fetched: $force_ver"
if [ "$force_ver" != "$LOCAL_VERSION" ]; then
  assert_contains "--version force-fetch warns about mismatch" "$STDERR" "$WARNING_NEEDLE"
else
  echo "  (cloud version matches local — no warning expected)"
fi

# ── Summary ───────────────────────────────────────────────────────────

echo
echo "==="
echo "$pass/$total passed, $fail failed"
[ "$fail" -eq 0 ]
